Một quá trình có thể được đóng băng tạm thời trong linux?


53

Tôi đã tự hỏi nếu có một cách để đóng băng bất kỳ quá trình trong một khoảng thời gian nhất định?

Ý tôi là: một ứng dụng (có thể đang chạy bằng root) có thể tạm dừng việc thực thi một quy trình đã chạy khác (bất kỳ quá trình nào, cả GUI và dòng lệnh) và sau đó tiếp tục lại sau? Nói cách khác, tôi không muốn các quy trình nhất định được lên lịch bởi bộ lập lịch linux trong một khoảng thời gian nhất định.

Câu trả lời:


81

Xem tại đây

hai tín hiệu có thể đình chỉ việc thực hiện một quy trình. Một là "duyên dáng", và một là "mạnh mẽ".

Cái "duyên dáng" là SIGTSTP, và mục đích của nó là "độc đáo" hỏi quá trình, nếu cảm thấy như vậy, vui lòng tạm dừng thực thi cho đến khi nhận được SIGCONT. Trong trường hợp SIGTSTP, quá trình có thể bỏ qua SIGTSTP và tiếp tục thực thi bằng mọi cách, vì vậy điều này đòi hỏi sự hợp tác từ một chương trình được thiết kế để xử lý SIGTSTP.

Cái "mạnh mẽ" là SIGSTOP, và mục đích của nó là đình chỉ tất cả các luồng không gian người dùng liên quan đến quá trình đó. Quá trình này không thể bỏ qua SIGSTOPvì nó bỏ qua SIGKILL(sau đó sẽ giết chết quá trình một cách mạnh mẽ).

Để gửi một tín hiệu tùy ý, bao gồm bất kỳ trong những người đề cập ở đây, bạn có thể sử dụng các chương trình như kill, killallhoặc pkill; hoặc sử dụng cuộc gọi hệ thống kill(2). Xem các trang của hệ điều hành của bạn để biết chi tiết về nền tảng / kiến ​​trúc / phiên bản và lỗi phụ thuộc vào bất kỳ điều nào ở trên. Lưu ý rằng từ "giết" trong tất cả các lệnh này và tòa nhà là một cách viết sai. Các lệnh này không được thiết kế, độc quyền, để chấm dứt các quá trình. Họ có thể làm điều đó bằng cách gửi một số tín hiệu nhất định; nhưng tín hiệu cũng có thể được sử dụng cho chức năng khác hơn là chấm dứt một quá trình. Ví dụ: SIGSTOPchỉ tạm dừng quá trình và đó chỉ là một trong một số tín hiệu có thể được gửi theo cách này.

Để thêm điều kiện tự động tiếp tục lại quá trình sau một khoảng thời gian, bạn sẽ cần sử dụng một số quy trình giám sát vẫn đang chạy và đặt hẹn giờ để đánh thức quá trình giám sát, sau đó lần lượt gọi kill(2)lại và gửi SIGCONTtín hiệu đến quá trình dừng, để yêu cầu kernel tiếp tục thực thi. Lưu ý rằng Linux có một số cơ chế thời gian với nhiều mức độ chính xác và chính xác khác nhau; hơn nữa, nếu hệ thống của bạn rất bận, quá trình giám sát của bạn có thể không được đánh thức cho đến khi hết giờ sau khi hết giờ, và do đó việc thức dậy có thể bị trì hoãn.

Nếu bạn phụ thuộc vào độ chính xác rất chính xác của hệ thống treo và nối lại các quá trình bị treo, bạn có thể cần phải chạy chương trình giám sát của bạn với các điều khoản real-time (xem manpage này trên sched_setscheduler(2)để biết thông tin về việc xử lý của bạn theo thời gian thực). Bạn cũng có thể sử dụng độ phân giải cao Timers, một tính năng của hạt nhân Linux (mà chỉ có sẵn nếu phần cứng của bạn cung cấp hỗ trợ cho họ), kết hợp với lịch trình thời gian thực, để có được rất chính xác, phụ millisecond chính xác về thời gian, sau đó thức dậy và gửi tín hiệu để tiếp tục quá trình theo dõi rất nhanh.

Bạn đã không chỉ ra những công nghệ mà bạn sẵn sàng sử dụng để thực hiện điều này. Ở mức tối thiểu, bạn sẽ cần ít nhất bash scripting, mặc dù bạn sẽ không thể có được thời gian rất chi tiết theo cách đó. Dưới đây là một "tập lệnh" bash (chưa được kiểm tra, vì vậy hãy cẩn thận) đó chỉ là một bằng chứng về khái niệm truy vấn của bạn. Nếu bạn cần thời gian chính xác, bạn sẽ phải viết một chương trình, có thể bằng C / C ++ hoặc ngôn ngữ bản địa khác, và sử dụng lập lịch và hrtimers theo thời gian thực.

#!/bin/bash
#This is the process you want to suspend.
screen -mdS child bash -c "cat /dev/urandom | base64"
#This is the process ID of the child process
THEPID=$(screen -list | grep child | cut -f1 -d'.' | sed 's/\W//g')
#Send SIGSTOP to the child process.
kill -SIGSTOP ${THEPID}
#Now it is suspended. This process will sleep for 10 seconds asynchronously, then resume the process.
screen -mdS monitor bash -c "sleep 10; kill -SIGCONT ${THEPID}"

Lưu ý rằng tập lệnh sẽ kết thúc và tập lệnh kiểm soát sẽ chấm dứt, nhưng do screenkiểm soát quá trình giám sát, nó sẽ tiếp tục chạy trong nền trong 10 giây (dựa trên đối số được truyền đến sleep) và sau đó thức dậy và tiếp tục quá trình con. Nhưng điều này sẽ rất lâu sau khi kịch bản kiểm soát kết thúc. Nếu bạn muốn chờ đồng bộ thời gian trôi qua, chỉ cần bỏ qua cuộc gọi thứ hai screenvà mã hóa chế độ ngủ và giết vào tập lệnh kiểm soát.

Bạn có thể kiểm tra xem thực tế quá trình có bị đình chỉ bằng cách chạy không

screen -rS child

sau khi bạn bắt đầu kịch bản này. Bạn sẽ không thấy bất cứ điều gì trên bảng điều khiển. Sau đó, sau khi hết giờ (10 giây), nó sẽ tràn vào màn hình của bạn với dữ liệu cơ sở64 (ký tự ngẫu nhiên từ 0-9 và AF). Nhấn Ctrl + C để thoát.


Rất tốt câu trả lời rất đầy đủ bao gồm đoạn bash PoC. Đẹp!
fgysin

Nếu một quá trình bị đóng băng ở giữa phiên mạng như kết nối TCP, khi nó được tiếp tục, phiên mạng đó có thể bị hỏng hoặc bị hủy không? Có một hành vi được xác định cho điều này?
CMCDragonkai

@cmcdragonkai vì khi dừng quá trình không chạy, nó không thể đọc hoặc ghi vào bất kỳ fd nào, nhưng kernel tiếp tục truyền byte cho đến khi bộ đệm của nó đầy trong một phiên TCP, tức là không chuyển giữa không gian kernel và không gian người dùng. quy trình đóng băng là kiểm tra khác nhau https://www.kernel.org/doc/Documentation/power/freezing-of-t
task.txt

Tôi đã thấy rằng các kết nối TCP có thể tiếp tục sau khi đưa quá trình trở lại nền trước (thời gian chờ là dành riêng cho ứng dụng, có TCP giữ nguyên nhưng cũng giữ mức độ ứng dụng). Quá trình đóng băng, dường như có nghĩa là khi máy tính ở chế độ ngủ đông hoặc chế độ ngủ. Có đúng không?
CMCDragonkai

Tập lệnh này không ảnh hưởng đến các mã không hợp tác: gist.github.com/ceremcem/864dd94b52ffe7b18da29558df4f1f5b
ceremcem

14

Có, bạn có thể làm điều đó bằng cách gửi tín hiệu STOP đến một quy trình để tạm dừng tín hiệu đó và sau đó tiếp tục TIẾP TỤC .

sử dụng:

kill -STOP <pid>

kill -CONT <pid>

11

Nếu bạn có một định nghĩa lỏng lẻo về "đóng băng", bạn có thể kiểm tra renicelệnh.

Renice cho phép bạn thay đổi mức độ ưu tiên lập lịch của các quy trình đang chạy.

Giá trị tốt của quy trình thông thường là 0. Tăng giá trị tốt giúp quy trình đẹp hơn, như trong "tại sao bạn không đi trước". Trong khi việc giảm giá trị tốt đẹp làm cho một quá trình trở nên tốt đẹp hơn, như trong "tránh ra, tôi đang vội". Phạm vi giá trị tốt đẹp là -20 đến 19.

Bất cứ ai cũng có thể làm cho quá trình riêng của họ đẹp hơn. Chỉ root mới có thể làm cho một quá trình kém đẹp hơn hoặc thay đổi người dùng khác xử lý tính tốt.

Nếu bạn đặt một quy trình có giá trị tốt là 19, nó sẽ chỉ chạy khi không có gì khác trên hệ thống muốn.

Đây là một ví dụ chạy trên hộp linux cục bộ của tôi.

Sử dụng ps -lvà nhìn vào cột NI để thấy một quy trình có giá trị tốt.

-> ps -l
FS UID PID PPID C PRI NI ĐỊA CHỈ SZ WCHAN TTY CMD
0 S 29190 402 31146 0 75 0 - 16547 chờ pts / 0 bash
0 T 29190 1105 402 0 75 0 - 23980 kết thúc pts / 0 vim
0 R 29190 794 402 0 76 0 - 15874 - điểm / 0 ps

Chạy renice +10trên tiến trình vim làm cho nó chạy ở mức ưu tiên thấp hơn.

-> gia hạn +10 -p 1105
1105: ưu tiên cũ 0, ưu tiên mới 10

-> ps -l
FS UID PID PPID C PRI NI ĐỊA CHỈ SZ WCHAN TTY CMD
0 S 29190 402 31146 0 76 0 - 16547 chờ pts / 0 bash
0 T 29190 1105 402 0 95 10 - 23980 kết thúc pts / 0 vim
0 R 29190 1998 402 0 78 0 - 15874 - điểm / 0 ps

Giả sử rằng bạn có thể kéo dài "đóng băng" có nghĩa là "không làm phiền bất kỳ ai khác trên hệ thống", bạn có thể viết kịch bản như:

gia hạn 20 -p <pid quan tâm>
ngủ <lượng thời gian nhất định>
gia hạn 0 -p <pid quan tâm>

(nhớ chạy nó với quyền root).


lưu ý rằng tôi đã lấy một số quyền tự do với ps -lđầu ra ở trên để có được các cột thú vị để hiển thị độc đáo trong các hộp nhỏ màu xanh :)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.