2009-07-24 42 views
6

Tôi có một chương trình chế độ bàn điều khiển sử dụng SQLite3 để duy trì tệp cơ sở dữ liệu. Phải mất một lúc để thực thi, nhưng nó sẽ an toàn tại bất kỳ thời điểm nào để hủy bỏ, giả sử rằng cơ sở dữ liệu ghi xảy ra. (Đây là tất cả các hệ điều hành Windows)TerminateProcess vs Ctrl + C

Có bất kỳ an toàn hơn, từ quan điểm của một chương trình đang chạy, để đạt CtrlC trong giao diện điều khiển hơn để có một TerminateProcess gọi chương trình trên đó?

Tôi đã nhận thấy rằng tôi có thể bị hỏng cơ sở dữ liệu nếu TerminateProcess được gọi- tôi giả định rằng điều này là do chương trình không có cơ hội hoàn tất quá trình ghi. Tôi đoán là CtrlC là tốt hơn, bởi vì chương trình nhận được tín hiệu và chấm dứt chính nó, thay vì hệ điều hành giết nó.

Lưu ý rằng chương trình không thực sự xử lý tín hiệu (trừ khi SQLite thực hiện); Tôi đang nói về các cơ chế mặc định tích hợp của các tệp thực thi Win32 để xử lý tín hiệu CtrlC.

Để làm rõ/đơn giản hóa gian hỏi cho rằng viết này vừa thực hiện:

fwrite(buf, 1024*1024, 1, stream); 

Trong ghi này, TerminateProcess sẽ hành xử khác nhau từ CtrlC?

Trả lời

5

Tất cả đều là các đối số hấp dẫn, nhưng cách duy nhất để biết chắc chắn là thử. Vì vậy, tôi đã viết một chương trình đơn giản phân bổ bộ đệm 1GB, gán một số dữ liệu cho nó, sau đó ghi nó vào một tệp bằng cách sử dụng một fwrite đơn().Tôi đã thử nhiều phương pháp để có được ghi vào "tham nhũng" dữ liệu (Tôi đã chờ đợi một file cắt ngắn, cụ thể):

  • Calling TerminateProcess (thông qua chức năng kill perl và Win32 :: Process :: Kill)
  • đánh CtrlC
  • Sử dụng "End Process" Task Manager của
  • Sử dụng Process "Kill Process" Explorer

Không có gì sẽ dừng ghi trong mọi trường hợp, tệp có kích thước chính xác và có dữ liệu chính xác. Và mặc dù "Kill" sẽ xảy ra ngay lập tức, quá trình sẽ kéo dài cho đến khi viết xong.

Có vẻ như kết luận rằng không có sự khác biệt giữa TerminateProcess và CtrlC từ một điểm I/O của View- khi ghi khởi động, nó dường như được bảo đảm để hoàn thành (trừ cúp điện).

+0

Rất intresting, tôi cho rằng các hoạt động IO hoàn thành bất kể, vì nó chỉ đơn giản là không có ý nghĩa để ngăn chặn nó, những gì nó có thể nó có thể làm khác hơn là dẫn đến tham nhũng. Phải là một cách khác để chặn TerminateProcess ẩn trong đó ở đâu đó. Công cụ thú vị. cảm ơn. – Gavin

+1

Tôi nghi ngờ TerminateProcess không thể giết an toàn quá trình trong khi nó thực hiện một syscall: bối cảnh thread ở giai đoạn đó là trong không gian hạt nhân, và buộc phải giết nó có thể bị rò rỉ tài nguyên hệ thống. Hệ điều hành có thể cài đặt các móc cho tất cả các luồng của quá trình hiện đang thực hiện trong không gian hạt nhân mà sẽ hủy bỏ chuỗi khi nó cố gắng trả về từ syscall. – pmdj

0

Xác nhận quyền sở hữu SQLite là nguyên tử, ngay cả khi mất điện, xem http://www.sqlite.org/atomiccommit.html.

Ngoại lệ duy nhất cho điều này là một số hệ thống đĩa sẽ báo cáo rằng ghi đã xảy ra thành công trước khi dữ liệu thực sự được ghi vào đĩa đệm, tức là dữ liệu nằm trong bộ đệm đĩa hoặc hệ điều hành nằm trong SQLite. Xem http://www.sqlite.org/lockingv3.html, phần 6.0 Cách làm hỏng tệp cơ sở dữ liệu của bạn.

Quy trình được chấm dứt must stop all running threads and complete pending I/O operations before they exit. Cần đảm bảo tính toàn vẹn dữ liệu, miễn là quy trình không bị lỗi.

+0

"Sự khác biệt duy nhất về vấn đề này giữa Ctrl-C và TerminateProcess là cách ứng dụng được viết để xử lý một trong các sự kiện này". Giả thuyết này hay bạn có bằng chứng nào để sao lưu? – arolson101

+0

Liên kết mà Manuel cho là dường như có thẩm quyền. Rõ ràng tôi đã đưa ra một giả định không chính xác về việc chấm dứt; nó phải đang chờ I/O giữ nhiệm vụ mở, thay vì lập trình viên chặn cuộc gọi kết thúc. Tôi đã chỉnh sửa câu trả lời của mình để phản ánh điều này. –

1

ứng dụng của bạn đã có cơ hội để xử lý CtrlCCtrlNghỉ, như nét chính hoặc tín hiệu (phụ thuộc vào cấu hình), có nghĩa là các ứng dụng có cơ hội để thực hiện một cảnh sạch sẽ, đây sẽ là một cách nhẹ nhàng hơn nhiều để chấm dứt một quá trình, cho phép nó thêm một chút thời gian thực hiện nếu không có gì khác. TerminateProcess là một cú đá trong răng, ứng dụng không thể xử lý nó, nó đến từ hạt nhân, và nếu ứng dụng có thể xử lý nó, điều này sẽ tạo ra tất cả các vấn đề với quá trình 'un killable' treo TerminateProcess của chúng. xử lý và từ chối thoát.

Khi tôi hiểu nó ngay sau khi TerminateProcess được gọi trong tiến trình, nó không thể thực thi mã nữa, không dọn dẹp, không tắt máy, nó kết thúc, bạn không thể xử lý nó, nó đơn giản sẽ không có ý nghĩa nếu bạn có thể, không phải từ quan điểm bảo mật.

Tuyệt vời bài viết dự án mã ở đây về xử lý các cửa sổ giao diện điều khiển tín hiệu:

http://www.codeproject.com/KB/winsdk/console_event_handling.aspx

Thực hiện một số tín hiệu trên xử lý bạn có thể đảm bảo rằng các ghi cơ sở dữ liệu có một cơ hội để hoàn thành trước khi thoát khỏi chương trình, chứ không phải là có thể để nó thành cơ hội.

Bạn có thể chặn TerminateProcess, nhưng chương trình 'không thực sự' lịch sự ', nó giống như lập trình bộ gốc, tôi đã thấy một bài viết hay về điều này tại rootkit.com để tìm kiếm' Process Invincibility 'khi bạn có quá trình bất khả chiến bại, nó có thể trong thời gian riêng của mình đóng cửa sau khi nhận được một 'yêu cầu', và thực hiện bất kỳ làm sạch trước khi hnad, nhưng điều này chắc chắn nhất là một hack.

Dường như với tôi mặc dù rằng CtrlC hành vi bạn hiện đang thấy là do nó không ngay lập tức kết thúc quá trình đang chạy.

0

Tôi tin rằng vì mục đích của bạn, an toàn hơn để sử dụng CtrlC. Điều này sẽ gây ra một tín hiệu để gửi đến chương trình để chấm dứt. Nếu chương trình không xử lý tín hiệu, nó sẽ chấm dứt ngay tại chỗ.

TerminateProcess buộc chấm dứt quá trình và bất kỳ chủ đề con nào.

Từ MSDN:

TerminateProcess Chức năng Chấm dứt quá trình xác định và tất cả các chủ đề của nó. ... Chú thích

Chức năng TerminateProcess được sử dụng để vô điều kiện gây ra một quá trình để thoát . Trạng thái dữ liệu toàn cầu được duy trì bởi các thư viện liên kết động (DLL) có thể bị xâm phạm nếu TerminateProcess được sử dụng thay vì ExitProcess.

TerminateProcess bắt đầu chấm dứt và trả lại ngay lập tức. Việc này dừng việc thực hiện tất cả các luồng trong quy trình và yêu cầu hủy tất cả các I/O đang chờ xử lý. Quá trình kết thúc bị chấm dứt không thể thoát cho đến khi tất cả các yêu cầu đang chờ xử lý hoặc bị hủy bỏ .

Quá trình không thể tự ngăn không cho bị chấm dứt.

Có nhiều cách để quy trình chặn TerminateProcess, nhưng tôi nghi ngờ SQLite3 sẽ làm điều đó.

+0

Bài viết của bạn dường như nói rằng không có sự khác biệt, nhưng bạn nói rằng nó an toàn hơn để sử dụng CTRL + C. Hãy nhớ rằng, chúng tôi đang nói về một chương trình không được ghi cụ thể để xử lý tín hiệu. Có lý do tại sao bạn nói rằng nó an toàn hơn để sử dụng CTRL + C? – arolson101

+0

CTRL + C sẽ không buộc chấm dứt quá trình và chủ đề con, nó sẽ chỉ bảo nó tắt máy. Nếu nó không được xử lý, sau đó nó chỉ thoát. TerminateProcess có thể gây ra tham nhũng dữ liệu toàn cầu như nó nói trên MSDN. Trong giải pháp của bạn, bạn nói rằng không có gì sẽ ngừng viết; đó là bởi vì ngay cả TerminateProcess sẽ không kết thúc nếu có I/O ("Quá trình chấm dứt không thể thoát cho đến khi tất cả các I/O đang chờ xử lý đã được hoàn thành hoặc hủy bỏ."). Đó cũng là trong MSDN. – Manuel

Các vấn đề liên quan