Bisakah suatu proses dibekukan sementara di linux?


53

Saya bertanya-tanya apakah ada cara untuk membekukan proses apa pun untuk jangka waktu tertentu?

Maksud saya adalah: apakah mungkin untuk satu aplikasi (mungkin berjalan sebagai root) untuk menghentikan sementara proses yang sudah berjalan lainnya (proses apa pun, baik GUI dan baris perintah) dan kemudian melanjutkannya nanti? Dengan kata lain saya tidak ingin proses tertentu dijadwalkan oleh scheduler linux untuk jangka waktu tertentu.

Jawaban:


81

Lihat di sini

Ada dua sinyal yang dapat menunda eksekusi suatu proses. Satu "anggun", dan satu "kuat".

Yang "anggun" adalah SIGTSTP, dan tujuannya adalah untuk "dengan baik" meminta proses, jika terasa seperti itu, untuk silakan menunda eksekusi sampai menerima a SIGCONT. Dalam hal ini SIGTSTP, proses dapat mengabaikan SIGTSTP dan melanjutkan eksekusi, jadi ini membutuhkan kerja sama dari program yang dirancang untuk menangani SIGTSTP.

Yang "kuat" adalah SIGSTOP, dan tujuannya adalah untuk menangguhkan semua utas pengguna yang terkait dengan proses itu. Sama tidak mungkin bagi proses untuk diabaikan SIGSTOPsebagaimana halnya untuk diabaikan SIGKILL(yang terakhir membunuh proses dengan paksa).

Untuk mengirim sinyal sewenang-wenang, termasuk salah satu yang disebutkan di sini, Anda dapat menggunakan program seperti kill, killall, atau pkill; atau gunakan panggilan sistem kill(2). Lihat halaman manual sistem operasi Anda untuk detail platform / arsitektur / versi-dependen dan errata mengenai salah satu di atas. Perhatikan bahwa kata "bunuh" dalam semua perintah ini dan syscall adalah istilah yang salah. Perintah-perintah ini tidak dirancang, secara eksklusif, untuk menghentikan proses. Mereka dapat melakukannya dengan mengirimkan sinyal tertentu; tetapi sinyal juga dapat digunakan untuk fungsi selain menghentikan proses. Misalnya, SIGSTOPhanya menunda proses, dan itu hanya salah satu dari beberapa sinyal yang dapat dikirim dengan cara ini.

Untuk menambahkan kondisi melanjutkan kembali proses secara otomatis setelah periode waktu berlalu, Anda harus menggunakan semacam proses pemantauan yang tetap berjalan dan mengatur timer untuk membangunkan proses pemantauan, yang kemudian akan memanggil kill(2)lagi dan mengirimkan SIGCONTsinyal ke proses yang dihentikan, untuk meminta kernel melanjutkan eksekusi. Perhatikan bahwa Linux memiliki beberapa mekanisme pengaturan waktu dengan berbagai tingkat akurasi dan presisi; lebih jauh lagi, jika sistem Anda sangat sibuk, proses pemantauan Anda mungkin tidak akan bangun sampai setelah waktu habis, dan dengan demikian bangun mungkin tertunda.

Jika Anda tergantung pada presisi sangat akurat dari suspensi dan dimulainya kembali proses ditangguhkan, Anda mungkin perlu untuk menjalankan program pemantauan Anda dengan izin real-time (lihat halaman manual ini pada sched_setscheduler(2)informasi tentang membuat proses Anda real-time). Anda juga dapat menggunakan Timer Resolusi Tinggi, sebuah fitur dari kernel Linux (yang hanya tersedia jika perangkat keras Anda menyediakan dukungan untuk mereka), dalam kombinasi dengan penjadwalan real-time, untuk mendapatkan ketepatan waktu sub-milidetik yang sangat akurat, mengenai pengaturan waktu, kemudian bangun dan kirim sinyal untuk melanjutkan proses yang dipantau dengan sangat cepat.

Anda tidak menunjukkan teknologi mana yang ingin Anda gunakan untuk mengimplementasikan ini. Minimal, Anda memerlukan setidaknya bash scripting, meskipun Anda tidak akan bisa mendapatkan waktu yang sangat halus seperti itu. Berikut ini adalah "skrip" bash (belum diuji, jadi harap berhati-hati) yang hanya merupakan bukti konsep permintaan Anda. Jika Anda membutuhkan pengaturan waktu yang tepat, Anda harus menulis sebuah program, mungkin dalam C / C ++ atau bahasa asli lainnya, dan menggunakan penjadwalan waktu nyata dan hrtimer.

#!/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}"

Perhatikan bahwa skrip akan berakhir dan skrip pengendali akan berakhir, tetapi karena screenmengendalikan proses monitor, skrip akan terus berjalan di latar belakang selama 10 detik (berdasarkan argumen yang diteruskan ke sleep) dan kemudian bangun dan melanjutkan proses anak. Tapi ini akan lama setelah skrip pengendali berakhir. Jika Anda ingin secara sinkron menunggu waktu berlalu, cukup abaikan panggilan kedua ke screendan kode-keras sleep dan bunuh ke skrip pengendali.

Anda dapat menguji bahwa proses itu sebenarnya ditangguhkan dengan menjalankan

screen -rS child

setelah Anda memulai skrip ini. Anda tidak akan melihat apa pun di konsol. Kemudian setelah timer berakhir (10 detik), itu akan membanjiri layar Anda dengan data base64 (karakter acak 0-9 dan AF). Tekan Ctrl + C untuk keluar.


Jawaban yang sangat bagus sangat lengkap termasuk cuplikan bash PoC. Bagus!
fgysin

Jika suatu proses membeku di tengah-tengah sesi jaringan seperti koneksi TCP, ketika itu dilanjutkan, dapatkah sesi jaringan itu rusak atau jatuh? Apakah ada perilaku yang pasti untuk ini?
CMCDragonkai

@cmcdragonkai karena ketika proses berhenti tidak berjalan, ia tidak dapat membaca atau menulis ke fd apa pun, tetapi kernel terus mentransfer byte hingga buffernya penuh dalam sesi TCP, yaitu tidak ada transfer antara ruang kernel dan ruang pengguna. proses pembekuan berbeda cek https://www.kernel.org/doc/Documentation/power/freezing-of-tasks.txt
Nizam Mohamed

Saya telah menemukan bahwa koneksi TCP dapat berlanjut setelah membawa proses kembali ke latar depan (timeout adalah spesifik aplikasi, ada TCP keepalive tetapi juga level-aplikasi keepalive). Proses pembekuan, tampaknya berarti ketika komputer dalam mode hibernasi atau tidur. Apakah itu benar?
CMCDragonkai

Skrip ini tidak berpengaruh pada kode non-kooperatif: gist.github.com/ceremcem/864dd94b52ffe7b18da29558df4f1f5b
ceremcem

14

Ya, Anda dapat melakukannya dengan mengirim sinyal STOP ke proses untuk menangguhkannya dan kemudian CONT untuk melanjutkan.

pemakaian:

kill -STOP <pid>

kill -CONT <pid>

11

Jika Anda memiliki definisi "pembekuan" yang longgar, Anda dapat memeriksa reniceperintahnya.

Renice memungkinkan Anda untuk mengubah prioritas penjadwalan proses yang berjalan.

Nilai bagus proses normal adalah 0. Meningkatkan nilai bagus membuat proses lebih bagus, seperti pada "kenapa Anda tidak pergi dulu". Sementara mengurangi nilai bagus membuat proses kurang bagus, seperti dalam "keluar dari jalan saya, saya sedang terburu-buru". Kisaran nilai yang bagus adalah -20 hingga 19.

Siapa pun dapat membuat proses mereka sendiri lebih baik. Hanya root yang dapat membuat proses kurang menyenangkan atau mengubah pengguna lain memproses kebaikan.

Jika Anda menetapkan nilai proses yang bagus menjadi 19, itu hanya akan berjalan ketika tidak ada hal lain di sistem yang mau.

Berikut adalah contoh yang dijalankan pada kotak linux lokal saya.

Gunakan ps -ldan lihat kolom NI untuk melihat proses nilai yang bagus.

-> ps -l
FS UID PID PPID C PRI NI ADDR SZ WCHAN TTY CMD
0 S 29190 402 31146 0 75 0 - 16547 tunggu poin / 0 bash
0 T 29190 1105 402 0 75 0 - 23980 titik penyelesaian / 0 vim
0 R 29190 794 402 0 76 0 - 15874 - Poin / 0 ps

Berjalan renice +10pada proses vim menyebabkannya berjalan pada prioritas yang lebih rendah.

-> renice +10 -p 1105
1105: prioritas lama 0, prioritas baru 10

-> ps -l
FS UID PID PPID C PRI NI ADDR SZ WCHAN TTY CMD
0 S 29190 402 31146 0 76 0 - 16547 tunggu poin / 0 bash
0 T 29190 1105 402 0 95 10 - 23980 titik akhir / 0 vim
0 R 29190 1998 402 0 78 0 - 15874 - Poin / 0 ps

Dengan asumsi bahwa Anda dapat memperluas "membekukan" berarti "tidak mengganggu orang lain pada sistem" Anda dapat membuat skrip sesuatu seperti:

renice 20 -p <pid of interest>
tidur <jumlah waktu tertentu>
renice 0 -p <pid of interest>

(ingat untuk menjalankannya sebagai root).


perhatikan bahwa saya mengambil beberapa kebebasan dengan ps -loutput di atas untuk mendapatkan kolom yang menarik untuk ditampilkan dengan baik di kotak biru kecil :)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.