2010-07-26 35 views
5

Tôi có một tập lệnh PHP độc lập và tôi sẽ xử lý tín hiệu được gửi từ hệ điều hành Windows để thực hiện tắt máy một cách duyên dáng khi "tín hiệu giết" được phát hành.Xử lý tín hiệu trên Windows

Tôi làm cách nào để thực hiện điều đó trên Windows?

Trả lời

3

Trong khi câu trả lời duy nhất ở đây là gọn gàng và chính xác, nó thiếu chi tiết về lý do tại sao không có hỗ trợ tín hiệu trên Windows.

Trước hết, các tín hiệu là một cách giao tiếp khá hạn chế và lỗi thời khi giao tiếp với một quy trình. Có nhiều cách phong phú hơn để thông báo cho một quá trình mà nó cần phải làm những gì nó đang làm và làm điều gì đó khác. Ngay cả trên nền tảng POSIX, bộ xử lý tín hiệu được dự định là RẤT nhẹ - mã trong bộ xử lý tín hiệu phải sẵn sàng/có khả năng xử lý nhiều tín hiệu đến cùng một lúc.

PHP cho phép xử lý tín hiệu qua số pcntl_signal() với số lượng đáng kể cảnh báo. Trước khi chúng có thể được sử dụng, mã phải điều chỉnh số lượng "ve" vượt qua trước khi PHP sẽ truyền tín hiệu đến một trình xử lý. Đánh dấu là số lượng lệnh mà Zend (lõi của PHP) sẽ thực hiện trước khi kiểm tra trạng thái xử lý tín hiệu và chạy các cuộc gọi lại cần thiết. Về cơ bản nó là một vòng lặp bận trong vòng lặp thực hiện chính. Như vậy, việc điều chỉnh ve sẽ làm chậm đáng kể quá trình nếu khuyến nghị mỗi lần đánh dấu của 1 được theo sau. Các ý kiến ​​về chức năng cho thấy một giá trị đánh dấu là 100 là đủ trên hầu hết các hệ thống. Cách dễ nhất để hiểu cách trình xử lý hoạt động là có một trình xử lý tín hiệu thực tế đằng sau hậu trường thu thập thông tin tín hiệu, mà PHP thỉnh thoảng truy vấn để xem trình xử lý có được gọi hay không, tín hiệu nào được gửi đi, v.v. thông tin được chuyển đến một cuộc gọi lại trong vùng người dùng (tức là mã của bạn). Nó không phải là xử lý tín hiệu thực sự và sẽ không bao giờ là do sự nguy hiểm và khó khăn mà việc xử lý tín hiệu thực.

Vấn đề thứ hai là, ngay cả với hỗ trợ xử lý tín hiệu giả mà pcntl_signal() cung cấp, PHP có thể mất thông tin về các tín hiệu đã xảy ra. Nếu kịch bản nhiều tín hiệu xảy ra, tập lệnh sẽ không được thông báo rằng một số tín hiệu đã xảy ra nhiều lần. Giá trị đánh dấu càng lớn, càng có nhiều khả năng điều này có thể xảy ra, đặc biệt là trên một hệ thống bận.

Windows, hầu hết, không thực sự sử dụng tín hiệu. Có chức năng SetConsoleCtrlHandler() tồn tại để nắm bắt Ctrl + C và Ctrl + Break và gần tương đương với SIGINT. Nhược điểm là phải có một giao diện điều khiển gắn liền với quá trình để nó hoạt động và không thể được gửi bởi các quá trình khác. Hàm TerminateProcess() tương đương với SIGKILL, không thể bị chặn/xử lý trong các hệ điều hành khác và tín hiệu SIGKILL không thực sự đến được quá trình đích. Ngoài hai chức năng/tín hiệu này, có rất ít điểm chung. Cuối cùng, Windows là một con thú rất khác nhau dưới mui xe. Lý do duy nhất để xem xét tín hiệu là một số loại quy trình PHP dài hạn - một nhiệm vụ mà mọi người dường như nói rằng ngôn ngữ không phù hợp (tôi hoàn toàn không đồng ý, nhưng đó là một cuộc thảo luận khác). Như tôi đã học về những hạn chế của sự hỗ trợ tín hiệu trong PHP ngay cả dưới hệ điều hành POSIX, tôi quyết định rằng chúng không thực sự là câu trả lời cho tình huống của tôi. Giải pháp đúng là bỏ qua tín hiệu hoàn toàn. Đối với SIGINT, các kịch bản lệnh dòng lệnh phải được viết để xử lý kịch bản kết thúc sớm - nghĩa là chúng phải là idempotent. Trong thế giới của PHP, các tín hiệu phần lớn không liên quan vì có các giải pháp khác, linh hoạt hơn và phong phú hơn bao gồm các mutexes/sự kiện, ổ cắm, tệp, tên được đặt tên, bộ nhớ chia sẻ, Service Manager, v.v.

4

PHP không hỗ trợ xử lý tín hiệu trên Windows. Lấy làm tiếc.

+1

Đặc biệt, cách duy nhất PHP có thể xử lý các tín hiệu là với hàm [pcntl_signal] (http://php.net/manual/en/function.pcntl-signal.php), một phần của phần mở rộng [pcntl] (http://www.php.net) /manual/en/intro.pcntl.php), không hoạt động trên Windows. – Charles

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