Rumah > Tutorial sistem > LINUX > teks badan

Mekanisme isyarat di bawah Linux: Cara menggunakan isyarat untuk komunikasi dan kawalan antara proses

WBOY
Lepaskan: 2024-02-12 12:40:03
ke hadapan
1166 orang telah melayarinya

Linux 下的信号机制:如何使用信号进行进程间通信和控制

Isyarat ialah kaedah komunikasi dan kawalan antara proses yang biasa digunakan dalam sistem Linux Ia membenarkan satu proses menghantar mesej ringkas kepada proses lain untuk memberitahunya bahawa peristiwa atau status tertentu telah berlaku. Fungsi isyarat adalah untuk meningkatkan responsif dan fleksibiliti sistem untuk menghadapi beberapa situasi yang tidak normal atau kecemasan. Dalam sistem Linux, terdapat banyak jenis isyarat, seperti SIGINT, SIGTERM, SIGKILL, dan lain-lain. Setiap daripadanya mempunyai maksud dan fungsi tersendiri, dan sesuai untuk senario dan keperluan yang berbeza. Tetapi, adakah anda benar-benar memahami mekanisme isyarat di bawah Linux? Adakah anda tahu cara menggunakan isyarat untuk komunikasi dan kawalan antara proses di bawah Linux? Adakah anda tahu cara mengendalikan dan mengabaikan isyarat dalam Linux? Artikel ini akan memperkenalkan anda kepada pengetahuan berkaitan mekanisme isyarat di bawah Linux secara terperinci, membolehkan anda menggunakan dan memahami kaedah komunikasi dan kawalan antara proses yang berkuasa ini dengan lebih baik di bawah Linux.

1. Konsep asas isyarat

Bahagian ini mula-mula memperkenalkan beberapa konsep asas isyarat, dan kemudian memberikan beberapa jenis isyarat asas dan peristiwa yang sepadan dengan isyarat. Konsep asas amat penting untuk memahami dan menggunakan isyarat, dan untuk memahami mekanisme isyarat. Mari kita lihat apa itu isyarat.

1. Konsep asas

Isyarat gangguan lembut (isyarat, juga dirujuk sebagai isyarat) digunakan untuk memberitahu proses bahawa peristiwa tak segerak telah berlaku. Proses boleh menghantar isyarat gangguan lembut antara satu sama lain melalui pembunuh panggilan sistem. Kernel juga boleh menghantar isyarat kepada proses disebabkan oleh peristiwa dalaman, memberitahu proses bahawa peristiwa telah berlaku. Ambil perhatian bahawa isyarat hanya digunakan untuk memberitahu proses tentang peristiwa yang telah berlaku dan tidak menghantar sebarang data kepada proses tersebut.

Proses yang menerima isyarat mempunyai kaedah pemprosesan yang berbeza untuk pelbagai isyarat. Kaedah pemprosesan boleh dibahagikan kepada tiga kategori: yang pertama ialah pengendali seperti gangguan Untuk isyarat yang perlu diproses, proses boleh menentukan fungsi pemprosesan, yang akan mengendalikannya. Kaedah kedua ialah mengabaikan isyarat dan tidak melakukan apa-apa dengan isyarat, seolah-olah ia tidak pernah berlaku. Kaedah ketiga adalah untuk mengekalkan nilai lalai sistem untuk memproses isyarat Operasi lalai ini, operasi lalai untuk kebanyakan isyarat adalah untuk menamatkan proses. Proses menggunakan isyarat panggilan sistem untuk menentukan tingkah laku pengendalian proses untuk isyarat tertentu.

Terdapat medan isyarat gangguan lembut dalam entri jadual proses Setiap bit dalam medan ini sepadan dengan isyarat Apabila isyarat dihantar ke proses, bit yang sepadan ditetapkan. Dari sini dapat dilihat bahawa proses boleh mengekalkan isyarat yang berbeza pada masa yang sama, tetapi untuk isyarat yang sama, proses itu tidak tahu berapa banyak yang telah datang sebelum diproses.

2. Jenis isyarat

Terdapat banyak sebab untuk menghantar isyarat Berikut adalah klasifikasi mudah mengikut sebab menghantar isyarat untuk memahami pelbagai isyarat:

(1) Isyarat yang berkaitan dengan penamatan proses. Isyarat jenis ini dipancarkan apabila proses keluar atau proses anak ditamatkan.
(2) Isyarat yang berkaitan dengan peristiwa pengecualian proses. Sebagai contoh, proses melintasi sempadan, atau cuba menulis ke kawasan ingatan baca sahaja (seperti kawasan teks program), atau melaksanakan arahan istimewa dan pelbagai ralat perkakasan lain.
(3) Isyarat yang berkaitan dengan menghadapi keadaan yang tidak boleh dipulihkan semasa panggilan sistem. Contohnya, apabila melaksanakan exec panggilan sistem, sumber asal telah dikeluarkan dan sumber sistem semasa telah habis.
(4) Isyarat yang berkaitan dengan menghadapi keadaan ralat bukan ramalan semasa melaksanakan panggilan sistem. Seperti melaksanakan panggilan sistem yang tidak wujud.
(5) Isyarat dihantar oleh proses dalam mod pengguna. Sebagai contoh, proses memanggil panggilan sistem membunuh untuk menghantar isyarat kepada proses lain.
(6) Isyarat yang berkaitan dengan interaksi terminal. Contohnya, pengguna menutup terminal atau menekan kekunci putus.
(7) Jejaki isyarat pelaksanaan proses.

Senarai isyarat yang disokong oleh Linux adalah seperti berikut. Banyak isyarat yang berkaitan dengan seni bina mesin Yang pertama disenaraikan adalah isyarat yang disenaraikan dalam POSIX.1:

Nilai isyarat Memproses tindakan Sebab menghantar isyarat
———————————————————————-

SIGHUP 1 A 终端挂起或者控制进程终止 
SIGINT 2 A 键盘中断(如break键被按下) 
SIGQUIT 3 C 键盘的退出键被按下 
SIGILL 4 C 非法指令 
SIGABRT 6 C 由abort(3)发出的退出指令 
SIGFPE 8 C 浮点异常 
SIGKILL 9 AEF Kill信号 
SIGSEGV 11 C 无效的内存引用 
SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道 
SIGALRM 14 A 由alarm(2)发出的信号 
SIGTERM 15 A 终止信号 
SIGUSR1 30,10,16 A 用户自定义信号1 
SIGUSR2 31,12,17 A 用户自定义信号2 
SIGCHLD 20,17,18 B 子进程结束信号 
SIGCONT 19,18,25 进程继续(曾被停止的进程) 
SIGSTOP 17,19,23 DEF 终止进程 
SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键 
SIGTTIN 21,21,26 D 后台进程企图从控制终端读 
SIGTTOU 22,22,27 D 后台进程企图从控制终端写 
Salin selepas log masuk

Isyarat berikut tidak disenaraikan dalam POSIX.1, tetapi disenaraikan dalam SUSv2

Nilai isyarat Memproses tindakan Sebab menghantar isyarat
——————————————————————–

SIGBUS 10,7,10 C 总线错误(错误的内存访问) 
SIGPOLL A Sys V定义的Pollable事件,与SIGIO同义 
SIGPROF 27,27,29 A Profiling定时器到 
SIGSYS 12,-,12 C 无效的系统调用 (SVID) 
SIGTRAP 5 C 跟踪/断点捕获 
SIGURG 16,23,21 B Socket出现紧急条件(4.2 BSD) 
SIGVTALRM 26,26,28 A 实际时间报警时钟信号(4.2 BSD) 
SIGXCPU 24,24,30 C 超出设定的CPU时间限制(4.2 BSD) 
SIGXFSZ 25,25,31 C 超出设定的文件大小限制(4.2 BSD) 

(对于SIGSYS,SIGXCPU,SIGXFSZ,以及某些机器体系结构下的SIGBUS,Linux缺省的动作是A (terminate),SUSv2 是C (terminate and dump core))。 
Salin selepas log masuk

Berikut adalah beberapa isyarat lain

Nilai isyarat Memproses tindakan Sebab menghantar isyarat
———————————————————————-

SIGIOT 6 C IO捕获指令,与SIGABRT同义 
SIGEMT 7,-,7 
SIGSTKFLT -,16,- A 协处理器堆栈错误 
SIGIO 23,29,22 A 某I/O操作现在可以进行了(4.2 BSD) 
SIGCLD -,-,18 A 与SIGCHLD同义 
SIGPWR 29,30,19 A 电源故障(System V) 
SIGINFO 29,-,- A 与SIGPWR同义 
SIGLOST -,-,- A 文件锁丢失 
SIGWINCH 28,28,20 B 窗口大小改变(4.3 BSD, Sun) 
SIGUNUSED -,31,- A 未使用的信号(will be SIGSYS) 
Salin selepas log masuk

(Di sini, - bermakna isyarat tidak dilaksanakan; terdapat tiga nilai yang diberi makna, nilai pertama biasanya sah pada Alpha dan Sparc, nilai tengah sepadan dengan i386 dan ppc dan sh, dan yang terakhir nilai sepadan dengan mips Isyarat 29 SIGINFO/SIGPWR pada Alpha, SIGLOST pada Sparc)

Maksud huruf dalam item tindakan pemprosesan adalah seperti berikut
A Tindakan lalai adalah untuk menamatkan proses
B Tindakan lalai ialah mengabaikan isyarat ini
Tindakan lalai C adalah untuk menamatkan proses dan melakukan dump imej kernel (teras dump)
D Tindakan lalai adalah untuk menghentikan proses
Isyarat E tidak boleh ditangkap
Isyarat F tidak boleh diabaikan

Isyarat yang diperkenalkan di atas disokong oleh sistem biasa. Nama, fungsi dan tindakan pemprosesan lalai pelbagai isyarat diperkenalkan dalam bentuk jadual. Maksud pelbagai tindakan pemprosesan lalai ialah: menamatkan program bermakna proses keluar daripada isyarat bermakna membuang isyarat tanpa memprosesnya bermakna program hang dan boleh dimulakan semula selepas memasuki keadaan berhenti, biasanya dalam Semasa penyahpepijatan (seperti panggilan sistem ptrace dump imej kernel merujuk kepada lambakan imej data proses dalam memori dan sebahagian daripada kandungan yang disimpan dalam struktur kernel proses ke sistem fail dalam format tertentu, dan proses keluar dari pelaksanaan. Dengan cara ini Faedahnya ialah ia memberikan kemudahan kepada pengaturcara untuk mendapatkan nilai data semasa proses dijalankan, membolehkan mereka menentukan punca pembuangan, dan menyahpepijat program mereka.

Perhatikan bahawa isyarat SIGKILL dan SIGSTOP tidak boleh ditangkap atau diabaikan. Isyarat SIGIOT dan SIGABRT adalah satu isyarat. Ia boleh dilihat bahawa isyarat yang sama mungkin mempunyai nilai yang berbeza dalam sistem yang berbeza, jadi adalah disyorkan untuk menggunakan nama yang ditakrifkan untuk isyarat dan bukannya secara langsung menggunakan nilai isyarat.

2. Mekanisme isyarat

Konsep asas isyarat telah diperkenalkan pada bahagian sebelumnya Dalam bahagian ini, kami akan memperkenalkan cara kernel melaksanakan mekanisme isyarat. Iaitu, bagaimana kernel menghantar isyarat kepada proses, bagaimana proses menerima isyarat, bagaimana proses mengawal tindak balasnya kepada isyarat, bila dan bagaimana kernel memproses isyarat yang diterima oleh proses tersebut. Saya juga ingin memperkenalkan peranan setjmp dan longjmp dalam isyarat.

1. Kaedah pemprosesan isyarat asas oleh kernel

Cara kernel menghantar isyarat gangguan lembut kepada proses adalah untuk menetapkan bit yang sepadan dengan isyarat dalam medan isyarat kemasukan jadual proses di mana proses itu terletak. Apa yang perlu ditambah di sini ialah jika isyarat dihantar ke proses tidur, maka ia bergantung kepada keutamaan proses memasuki tidur Jika proses tidur pada keutamaan yang boleh diganggu, proses itu dikejutkan; isyarat dalam jadual proses ditetapkan bit sepadan tanpa membangunkan proses. Ini penting kerana masa untuk proses menyemak sama ada isyarat telah diterima ialah apabila proses akan kembali daripada mod kernel kepada mod pengguna atau apabila proses akan memasuki atau meninggalkan keadaan tidur keutamaan rendah yang sesuai.

Masa untuk kernel memproses isyarat yang diterima oleh proses adalah apabila proses kembali dari mod kernel ke mod pengguna. Oleh itu, apabila proses berjalan dalam mod kernel, isyarat gangguan lembut tidak berkuat kuasa serta-merta dan mesti menunggu sehingga ia kembali ke mod pengguna. Proses akan kembali ke mod pengguna hanya selepas memproses isyarat Proses tidak akan mempunyai isyarat yang belum diproses dalam mod pengguna.

Krisis mengendalikan isyarat gangguan lembut yang diterima oleh proses dalam konteks proses, oleh itu, proses mestilah dalam keadaan berjalan. Seperti yang dinyatakan sebelum ini semasa memperkenalkan konsep, terdapat tiga jenis pemprosesan isyarat: proses keluar selepas menerima isyarat dan selepas proses menerima isyarat, ia melaksanakan fungsi yang ditetapkan oleh pengguna untuk memanggil isyarat; sistem tersebut. Apabila proses menerima isyarat yang diabaikan, proses itu membuang isyarat dan berterusan seolah-olah isyarat tidak diterima. Jika proses menerima isyarat untuk ditangkap, fungsi yang ditentukan pengguna dilaksanakan apabila proses kembali dari mod kernel ke mod pengguna. Selain itu, kaedah melaksanakan fungsi yang ditentukan pengguna adalah sangat bijak Kernel mencipta lapisan baharu pada timbunan pengguna Dalam lapisan ini, nilai alamat pemulangan ditetapkan kepada alamat fungsi pemprosesan yang ditentukan pengguna, supaya apabila proses kembali daripada kernel dan muncul bahagian atas tindanan Ia kembali kepada fungsi yang ditentukan pengguna, dan apabila ia kembali daripada fungsi dan muncul bahagian atas tindanan, ia kembali ke tempat ia mula-mula memasuki kernel. Sebabnya ialah fungsi pemprosesan yang ditentukan pengguna tidak boleh dan tidak dibenarkan untuk dilaksanakan dalam mod kernel (jika fungsi yang ditentukan pengguna berjalan dalam mod kernel, pengguna boleh mendapatkan sebarang kebenaran).

Terdapat beberapa perkara yang perlu diberi perhatian khusus dalam kaedah pemprosesan isyarat. Pertama, dalam sesetengah sistem, apabila proses mengendalikan isyarat gangguan dan kembali ke mod pengguna, kernel mengosongkan alamat rutin pemprosesan isyarat yang ditetapkan dalam kawasan pengguna, iaitu, pada kali seterusnya proses menukar kaedah pemprosesan isyarat, nilai lalai melainkan panggilan sistem isyarat digunakan semula sebelum isyarat seterusnya tiba. Ini boleh menyebabkan proses mendapatkan isyarat sebelum memanggil isyarat, menyebabkan ia keluar. Dalam BSD, kernel tidak lagi mengosongkan alamat ini. Tetapi tidak mengosongkan alamat ini boleh menyebabkan proses mendapat isyarat terlalu cepat dan menyebabkan limpahan tindanan. Bagi mengelakkan situasi di atas. Dalam sistem BSD, kernel mensimulasikan kaedah pemprosesan gangguan perkakasan, iaitu, apabila memproses gangguan, ia menghalang penerimaan gangguan baru jenis ini.

Perkara kedua yang perlu diperhatikan ialah jika isyarat yang akan ditangkap berlaku apabila proses berada dalam panggilan sistem, dan proses tidur pada tahap keutamaan yang boleh terganggu, maka isyarat menyebabkan proses melakukan longjmp dan melompat keluar dari tidur state. , kembali ke mod pengguna dan laksanakan rutin pemprosesan isyarat. Apabila kembali daripada rutin pengendalian isyarat, proses itu berkelakuan seolah-olah ia telah kembali daripada panggilan sistem, tetapi mengembalikan kod ralat yang menunjukkan bahawa panggilan sistem telah terganggu. Perlu diingatkan bahawa dalam sistem BSD kernel boleh memulakan semula panggilan sistem secara automatik.

Perkara ketiga yang perlu diambil perhatian: Jika proses tidur pada tahap keutamaan yang boleh terganggu, apabila ia menerima isyarat untuk diabaikan, proses itu akan dikejutkan, tetapi tidak melakukan longjmp, dan biasanya terus tidur. Tetapi pengguna tidak merasakan bahawa proses itu telah dikejutkan, tetapi seolah-olah isyarat tidak berlaku.

Perkara keempat yang perlu diberi perhatian: Inti mengendalikan isyarat penamatan proses kanak-kanak (SIGCLD) secara berbeza daripada isyarat lain. Apabila proses menyemak bahawa ia telah menerima isyarat untuk menamatkan proses kanak-kanak, secara lalai, proses itu bertindak seolah-olah ia tidak menerima isyarat Jika proses induk melaksanakan tunggu panggilan sistem, proses itu akan bangun daripada panggilan sistem tunggu dan Kembali ke panggilan tunggu, lakukan satu siri operasi susulan panggilan tunggu (cari proses anak zombi, lepaskan kemasukan jadual proses proses anak), dan kemudian kembali dari menunggu. Fungsi isyarat SIGCLD adalah untuk membangunkan proses tidur pada tahap keutamaan yang boleh terganggu. Jika proses menangkap isyarat, ia pergi ke rutin pengendali sama seperti pengendalian isyarat biasa. Jika proses mengabaikan isyarat, tindakan menunggu panggilan sistem adalah berbeza, kerana fungsi SIGCLD hanya untuk membangunkan proses tidur pada tahap keutamaan yang boleh terganggu, maka proses induk yang melaksanakan panggilan tunggu akan dibangkitkan dan terus laksanakan panggilan tunggu, dan kemudian tunggu proses anak lain.

Jika proses memanggil panggilan sistem isyarat dan menetapkan kaedah pemprosesan SIGCLD, dan proses tersebut mempunyai proses anak dalam keadaan zombie, kernel akan menghantar isyarat SIGCLD kepada proses tersebut.

2. Fungsi setjmp dan longjmp

Apabila memperkenalkan mekanisme pemprosesan isyarat tadi, setjmp dan longjmp disebut berkali-kali, tetapi fungsi dan kaedah pelaksanaannya tidak dijelaskan secara terperinci. Berikut adalah pengenalan ringkas untuk ini.

Semasa memperkenalkan isyarat, kami melihat beberapa tempat yang memerlukan proses untuk kembali terus daripada panggilan sistem asal selepas menyemak sama ada isyarat diterima, dan bukannya menunggu panggilan selesai. Keadaan ini di mana proses tiba-tiba berubah konteks adalah hasil daripada menggunakan setjmp dan longjmp. setjmp menyimpan konteks yang disimpan dalam kawasan pengguna dan meneruskan pelaksanaan dalam konteks lama. Maksudnya, proses melaksanakan panggilan sistem Apabila ia tidur kerana sumber atau sebab lain, kernel membuat setjmp untuk proses tersebut Jika ia dikejutkan oleh isyarat semasa tidur dan proses tidak boleh tidur semula , kernel memanggil longjmp untuk proses Operasi ini adalah untuk kernel memulihkan konteks yang disimpan dalam kawasan pengguna proses dengan panggilan setjmp asal kepada konteks semasa, supaya proses boleh kembali ke keadaan sebelum menunggu. untuk sumber, dan kernel mengembalikan 1 untuk setjmp, supaya proses mengetahui bahawa panggilan sistem gagal. Itulah yang mereka lakukan.

3. Panggilan sistem yang berkaitan dengan isyarat

Kebanyakan pengetahuan tentang isyarat telah diperkenalkan dalam dua bahagian sebelumnya. Dalam bahagian ini kita akan mempelajari tentang panggilan sistem ini. Antaranya, isyarat panggilan sistem digunakan oleh proses untuk menetapkan kaedah pemprosesan isyarat tertentu, dan pembunuh panggilan sistem digunakan untuk menghantar isyarat kepada proses yang ditentukan. Kedua-dua panggilan ini membentuk operasi asas isyarat. Dua panggilan terakhir, jeda dan penggera, adalah jeda proses dan pemasa dilaksanakan melalui isyarat. Penggera panggilan digunakan untuk memberitahu proses tamat tempoh pemasa melalui isyarat. Jadi di sini, kami juga memperkenalkan dua panggilan ini.

1. Panggilan sistem isyarat

Isyarat panggilan sistem digunakan untuk menetapkan kaedah pemprosesan isyarat tertentu. Pengisytiharan panggilan mempunyai format berikut:
void (*signal(int signum, void (*pengendali)(int)))(int);
Tambahkan fail pengepala berikut pada proses menggunakan panggilan ini:
#include

Format pengisytiharan di atas agak rumit Jika anda tidak tahu cara menggunakannya, anda juga boleh menggunakannya melalui format definisi jenis berikut (definisi POSIX):
. typedef void (*sighandler_t)(int);
isyarat sighandler_t(int signum, pengendali sighandler_t);
Walau bagaimanapun, format ini mempunyai definisi jenis yang berbeza dalam sistem yang berbeza, jadi untuk menggunakan format ini, sebaiknya merujuk kepada manual dalam talian.

Dalam panggilan, tanda tanda parameter menunjukkan isyarat yang akan ditetapkan untuk mengendalikan kaedah. Pengendali parameter kedua ialah fungsi pemprosesan, atau
SIG_IGN: Abaikan isyarat yang ditunjukkan oleh tanda tanda parameter.
SIG_DFL: Pulihkan kaedah pemprosesan isyarat yang ditunjuk oleh tanda parameter kepada nilai lalai.

Parameter integer yang dihantar kepada rutin pemprosesan isyarat ialah nilai isyarat, yang membolehkan satu rutin pemprosesan isyarat memproses berbilang isyarat. Nilai pulangan isyarat panggilan sistem ialah rutin pemprosesan sebelumnya bagi tanda isyarat yang ditentukan atau kod ralat SIG_ERR dikembalikan sekiranya berlaku ralat. Mari lihat contoh mudah:

#include 
\#include 
\#include 
void sigroutine(int dunno) { /* 信号处理例程,其中dunno将会得到信号的值 */ 
switch (dunno) { 
case 1: 
printf("Get a signal -- SIGHUP "); 
break; 
case 2: 
printf("Get a signal -- SIGINT "); 
break; 
case 3: 
printf("Get a signal -- SIGQUIT "); 
break; 
} 
return; 
} 

int main() { 
printf("process id is %d ",getpid()); 
signal(SIGHUP, sigroutine); //* 下面设置三个信号的处理方法 
signal(SIGINT, sigroutine); 
signal(SIGQUIT, sigroutine); 
for (;;) ; 
} 
Salin selepas log masuk

其中信号SIGINT由按下Ctrl-C发出,信号SIGQUIT由按下Ctrl-发出。该程序执行的结果如下:

localhost:~$ ./sig_test 
process id is 463 
Get a signal -SIGINT //按下Ctrl-C得到的结果 
Get a signal -SIGQUIT //按下Ctrl-得到的结果 
//按下Ctrl-z将进程置于后台 
[1]+ Stopped ./sig_test 
localhost:~$ bg 
[1]+ ./sig_test & 
localhost:~$ kill -HUP 463 //向进程发送SIGHUP信号 
localhost:~$ Get a signal – SIGHUP 
kill -9 463 //向进程发送SIGKILL信号,终止进程 
localhost:~$ 
Salin selepas log masuk

2、kill 系统调用

系统调用kill用来向进程发送一个信号。该调用声明的格式如下:
int kill(pid_t pid, int sig);
在使用该调用的进程中加入以下头文件:

\#include 
\#include 
Salin selepas log masuk

该 系统调用可以用来向任何进程或进程组发送任何信号。如果参数pid是正数,那么该调用将信号sig发送到进程号为pid的进程。如果pid等于0,那么信 号sig将发送给当前进程所属进程组里的所有进程。如果参数pid等于-1,信号sig将发送给除了进程1和自身以外的所有进程。如果参数pid小于- 1,信号sig将发送给属于进程组-pid的所有进程。如果参数sig为0,将不发送信号。该调用执行成功时,返回值为0;错误时,返回-1,并设置相应 的错误代码errno。下面是一些可能返回的错误代码:
EINVAL:指定的信号sig无效。
ESRCH:参数pid指定的进程或进程组不存在。注意,在进程表项中存在的进程,可能是一个还没有被wait收回,但已经终止执行的僵死进程。
EPERM: 进程没有权力将这个信号发送到指定接收信号的进程。因为,一个进程被允许将信号发送到进程pid时,必须拥有root权力,或者是发出调用的进程的UID 或EUID与指定接收的进程的UID或保存用户ID(savedset-user-ID)相同。如果参数pid小于-1,即该信号发送给一个组,则该错误 表示组中有成员进程不能接收该信号。

3、pause系统调用

系统调用pause的作用是等待一个信号。该调用的声明格式如下:
int pause(void);
在使用该调用的进程中加入以下头文件:
#include

该调用使得发出调用的进程进入睡眠,直到接收到一个信号为止。该调用总是返回-1,并设置错误代码为EINTR(接收到一个信号)。下面是一个简单的范例:

#include 
\#include 
\#include 
void sigroutine(int unused) { 
printf("Catch a signal SIGINT "); 
} 

int main() { 
signal(SIGINT, sigroutine); 
pause(); 
printf("receive a signal "); 
} 
Salin selepas log masuk

在这个例子中,程序开始执行,就象进入了死循环一样,这是因为进程正在等待信号,当我们按下Ctrl-C时,信号被捕捉,并且使得pause退出等待状态。

4、alarm和 setitimer系统调用

系统调用alarm的功能是设置一个定时器,当定时器计时到达时,将发出一个信号给进程。该调用的声明格式如下:
unsigned int alarm(unsigned int seconds);
在使用该调用的进程中加入以下头文件:
#include

系 统调用alarm安排内核为调用进程在指定的seconds秒后发出一个SIGALRM的信号。如果指定的参数seconds为0,则不再发送 SIGALRM信号。后一次设定将取消前一次的设定。该调用返回值为上次定时调用到发送之间剩余的时间,或者因为没有前一次定时调用而返回0。

注意,在使用时,alarm只设定为发送一次信号,如果要多次发送,就要多次使用alarm调用。

对于alarm,这里不再举例。现在的系统中很多程序不再使用alarm调用,而是使用setitimer调用来设置定时器,用getitimer来得到定时器的状态,这两个调用的声明格式如下:
int getitimer(int which, struct itimerval *value);
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);
在使用这两个调用的进程中加入以下头文件:
#include

该系统调用给进程提供了三个定时器,它们各自有其独有的计时域,当其中任何一个到达,就发送一个相应的信号给进程,并使得计时器重新开始。三个计时器由参数which指定,如下所示:
TIMER_REAL:按实际时间计时,计时到达将给进程发送SIGALRM信号。
ITIMER_VIRTUAL:仅当进程执行时才进行计时。计时到达将发送SIGVTALRM信号给进程。
ITIMER_PROF:当进程执行时和系统为该进程执行动作时都计时。与ITIMER_VIR-TUAL是一对,该定时器经常用来统计进程在用户态和内核态花费的时间。计时到达将发送SIGPROF信号给进程。

定时器中的参数value用来指明定时器的时间,其结构如下:

struct itimerval { 
struct timeval it_interval; /* 下一次的取值 */ 
struct timeval it_value; /* 本次的设定值 */ 
}; 

该结构中timeval结构定义如下: 
struct timeval { 
long tv_sec; /* 秒 */ 
long tv_usec; /* 微秒,1秒 = 1000000 微秒*/ 
}; 
Salin selepas log masuk

在setitimer 调用中,参数ovalue如果不为空,则其中保留的是上次调用设定的值。定时器将it_value递减到0时,产生一个信号,并将it_value的值设 定为it_interval的值,然后重新开始计时,如此往复。当it_value设定为0时,计时器停止,或者当它计时到期,而it_interval 为0时停止。调用成功时,返回0;错误时,返回-1,并设置相应的错误代码errno:
EFAULT:参数value或ovalue是无效的指针。
EINVAL:参数which不是ITIMER_REAL、ITIMER_VIRT或ITIMER_PROF中的一个。

下面是关于setitimer调用的一个简单示范,在该例子中,每隔一秒发出一个SIGALRM,每隔0.5秒发出一个SIGVTALRM信号:

#include 
\#include 
\#include 
\#include 
int sec; 

void sigroutine(int signo) { 
switch (signo) { 
case SIGALRM: 
printf("Catch a signal -- SIGALRM "); 
break; 
case SIGVTALRM: 
printf("Catch a signal -- SIGVTALRM "); 
break; 
} 
return; 
} 

int main() { 
struct itimerval value,ovalue,value2; 
sec = 5; 

printf("process id is %d ",getpid()); 
signal(SIGALRM, sigroutine); 
signal(SIGVTALRM, sigroutine); 

value.it_value.tv_sec = 1; 
value.it_value.tv_usec = 0; 
value.it_interval.tv_sec = 1; 
value.it_interval.tv_usec = 0; 
setitimer(ITIMER_REAL, &value, &ovalue); 

value2.it_value.tv_sec = 0; 
value2.it_value.tv_usec = 500000; 
value2.it_interval.tv_sec = 0; 
value2.it_interval.tv_usec = 500000; 
setitimer(ITIMER_VIRTUAL, &value2, &ovalue); 

for (;;) ; 
} 
Salin selepas log masuk

该例子的屏幕拷贝如下:

localhost:~$ ./timer_test 
process id is 579 
Catch a signal – SIGVTALRM 
Catch a signal – SIGALRM 
Catch a signal – SIGVTALRM 
Catch a signal – SIGVTALRM 
Catch a signal – SIGALRM 
Catch a signal –GVTALRM
Salin selepas log masuk

通过本文,你应该对 Linux 下的信号机制有了一个深入的了解,知道了它的定义、原理、用法和优缺点。你也应该明白了信号机制的作用和影响,以及如何在 Linux 下正确地使用和处理信号。我们建议你在使用 Linux 系统时,使用信号机制来提高系统的响应性和灵活性。同时,我们也提醒你在使用信号机制时要注意一些潜在的问题和挑战,如信号丢失、信号屏蔽、信号安全等。希望本文能够帮助你更好地使用 Linux 系统,让你在 Linux 下掌握信号机制的使用和处理。

Atas ialah kandungan terperinci Mekanisme isyarat di bawah Linux: Cara menggunakan isyarat untuk komunikasi dan kawalan antara proses. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:lxlinux.net
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan