Table des matières
1.Concepts de base des signaux" >1.Concepts de base des signaux
1.Concepts de base" >1.Concepts de base
2. Type de signal" >2. Type de signal
2. Mécanisme de signal" >2. Mécanisme de signal
3. Appels système liés aux signaux" >3. Appels système liés aux signaux
4、alarm和 setitimer系统调用" >4、alarm和 setitimer系统调用
Maison Tutoriel système Linux Mécanisme de signal sous Linux : Comment utiliser les signaux pour la communication et le contrôle inter-processus

Mécanisme de signal sous Linux : Comment utiliser les signaux pour la communication et le contrôle inter-processus

Feb 12, 2024 pm 12:40 PM
linux linux教程 linux系统 linux命令 shell脚本 typedef Linux embarqué Débuter avec Linux apprentissage Linux

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

Le signal est une méthode de communication et de contrôle inter-processus couramment utilisée dans les systèmes Linux. Il permet à un processus d'envoyer un message simple à un autre processus pour l'informer qu'un certain événement ou statut s'est produit. La fonction des signaux est d'améliorer la réactivité et la flexibilité du système pour faire face à certaines situations anormales ou d'urgence. Dans le système Linux, il existe de nombreux types de signaux, tels que SIGINT, SIGTERM, SIGKILL, etc. Chacun d'eux a sa propre signification et fonction et convient à différents scénarios et besoins. Mais comprenez-vous vraiment le mécanisme du signal sous Linux ? Savez-vous comment utiliser les signaux pour la communication et le contrôle inter-processus sous Linux ? Savez-vous comment gérer et ignorer les signaux sous Linux ? Cet article vous présentera en détail les connaissances pertinentes du mécanisme de signal sous Linux, vous permettant de mieux utiliser et comprendre cette puissante méthode de communication et de contrôle inter-processus sous Linux.

1.Concepts de base des signaux

Cette section présente d'abord quelques concepts de base sur les signaux, puis donne quelques types de signaux de base et événements correspondant aux signaux. Les concepts de base sont particulièrement importants pour comprendre et utiliser les signaux, ainsi que pour comprendre les mécanismes de signalisation. Voyons ce qu'est un signal.

1.Concepts de base

Le signal d'interruption douce (signal, également appelé signal) est utilisé pour informer le processus qu'un événement asynchrone s'est produit. Les processus peuvent s'envoyer des signaux d'interruption logicielle via l'appel système kill. Le noyau peut également envoyer des signaux au processus en raison d'événements internes, l'informant qu'un événement s'est produit. Notez que les signaux ne sont utilisés que pour informer un processus des événements qui se sont produits et ne transmettent aucune donnée au processus.

Le processus qui reçoit le signal a différentes méthodes de traitement pour différents signaux. Les méthodes de traitement peuvent être divisées en trois catégories : la première est un gestionnaire de type interruption. Pour le signal qui doit être traité, le processus peut spécifier une fonction de traitement qui le gérera. La deuxième méthode consiste à ignorer un signal et à ne rien faire avec ce signal, comme si cela ne s'était jamais produit. La troisième méthode consiste à conserver la valeur par défaut du système pour traiter le signal. Cette opération par défaut, l'opération par défaut pour la plupart des signaux consiste à terminer le processus. Le processus utilise le signal d'appel système pour spécifier le comportement de traitement du processus pour un certain signal.

Il y a un champ de signal d'interruption logicielle dans l'entrée de la table de processus. Chaque bit de ce champ correspond à un signal lorsqu'un signal est envoyé au processus, le bit correspondant est défini. On peut voir de là que le processus peut retenir différents signaux en même temps, mais pour un même signal, le processus ne sait pas combien sont venus avant le traitement.

2. Type de signal

Il existe de nombreuses raisons d'envoyer des signaux. Voici des classifications simples selon les raisons d'envoyer des signaux pour comprendre divers signaux :

(1) Signaux liés à la fin du processus. Ce type de signal est émis lorsque le processus se termine ou que le processus enfant se termine.
(2) Signaux liés aux événements d'exception de processus. Par exemple, le processus franchit la limite, ou tente d'écrire dans une zone de mémoire en lecture seule (telle que la zone de texte du programme), ou exécute une instruction privilégiée et diverses autres erreurs matérielles.
(3) Signaux liés à la rencontre de conditions irrécupérables lors des appels système. Par exemple, lors de l'exécution de l'appel système exec, les ressources d'origine ont été libérées et les ressources système actuelles ont été épuisées.
(4) Signaux liés à la rencontre de conditions d'erreur non prédictives lors de l'exécution d'appels système. Comme exécuter un appel système qui n’existe pas.
(5) Signaux envoyés par les processus en mode utilisateur. Par exemple, un processus appelle l'appel système kill pour envoyer des signaux à d'autres processus.
(6) Signaux liés à l'interaction du terminal. Par exemple, l'utilisateur ferme un terminal ou appuie sur la touche pause.
(7) Suivre les signaux d'exécution du processus.

La liste des signaux pris en charge par Linux est la suivante. De nombreux signaux sont liés à l'architecture de la machine. Les premiers répertoriés sont les signaux répertoriés dans POSIX.1 :

Valeur du signal Action de traitement Raison de l'envoi du signal
———————————————————————-

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 后台进程企图从控制终端写 
Copier après la connexion

Les signaux suivants ne sont pas répertoriés dans POSIX.1, mais sont répertoriés dans SUSv2

Valeur du signal Action de traitement Raison de l'envoi du signal
——————————————————————–

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))。 
Copier après la connexion

Voici quelques autres signaux

Valeur du signal Action de traitement Raison de l'envoi du signal
———————————————————————-

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) 
Copier après la connexion

(Ici, - signifie que le signal n'est pas implémenté ; il y a trois valeurs​​étant donné la signification, la première valeur est généralement valable sur Alpha et Sparc, la valeur du milieu correspond à i386 et ppc et sh, et la dernière la valeur correspond au signal mips 29 SIGINFO/SIGPWR sur Alpha, SIGLOST sur Sparc)

La signification des lettres dans l'élément d'action de traitement est la suivante
A L'action par défaut est de terminer le processus
B L'action par défaut est d'ignorer ce signal
L'action par défaut de C est de terminer le processus et d'effectuer un vidage d'image du noyau (dump core)
D L'action par défaut est d'arrêter le processus
Le signal E ne peut pas être capturé
Le signal F ne peut pas être ignoré

Les signaux introduits ci-dessus sont pris en charge par des systèmes courants. Les noms, fonctions et actions de traitement des différents signaux par défaut sont présentés sous forme de tableau. Les significations des différentes actions de traitement par défaut sont : terminer le programme signifie que le processus se termine ; ignorer le signal signifie ignorer le signal sans le traiter ; signifie que le programme se bloque et peut être redémarré après être entré dans l'état arrêté, généralement pendant ; le débogage (comme l'appel système ptrace) ; le vidage de l'image du noyau fait référence au vidage de l'image des données de processus en mémoire et d'une partie du contenu stocké dans la structure du noyau du processus vers le système de fichiers dans un certain format, et le processus quitte l'exécution. De cette façon, l'avantage est qu'il offre aux programmeurs la commodité d'obtenir des valeurs de données pendant l'exécution du processus, leur permettant de déterminer la cause du vidage et de déboguer leurs programmes.

Notez que les signaux SIGKILL et SIGSTOP ne peuvent être ni captés ni ignorés. Les signaux SIGIOT et SIGABRT forment un seul signal. On peut voir qu'un même signal peut avoir des valeurs différentes selon les systèmes, il est donc recommandé d'utiliser le nom défini pour le signal plutôt que d'utiliser directement la valeur du signal.

2. Mécanisme de signal

Le concept de base des signaux a été introduit dans la section précédente, nous présenterons comment le noyau implémente le mécanisme de signal. C'est-à-dire comment le noyau envoie un signal à un processus, comment le processus reçoit un signal, comment le processus contrôle sa réponse au signal, quand et comment le noyau traite le signal reçu par le processus. Je voudrais également présenter le rôle que jouent setjmp et longjmp dans les signaux.

1. Méthodes de base de traitement du signal par le noyau

La façon dont le noyau envoie un signal d'interruption logicielle à un processus consiste à définir le bit correspondant au signal dans le champ de signal de l'entrée de la table de processus où se trouve le processus. Ce qu'il faut ajouter ici, c'est que si le signal est envoyé à un processus en veille, cela dépend de la priorité du processus qui entre en veille. Si le processus dort avec une priorité qui peut être interrompue, le processus est réveillé sinon seul le processus. Le signal dans la table de processus est défini sur le champ correspondant au bit sans réveiller le processus. Ceci est important car le moment où un processus vérifie si un signal a été reçu est lorsqu'un processus est sur le point de revenir du mode noyau au mode utilisateur ou lorsqu'un processus est sur le point d'entrer ou de sortir d'un état de veille de faible priorité appropriée ;

Le moment auquel le noyau traite un signal reçu par un processus correspond au moment où un processus revient du mode noyau au mode utilisateur. Par conséquent, lorsqu'un processus s'exécute en mode noyau, le signal d'interruption logicielle ne prend pas effet immédiatement et doit attendre qu'il revienne en mode utilisateur. Le processus reviendra en mode utilisateur seulement après avoir traité le signal. Le processus n'aura pas de signaux non traités en mode utilisateur.

Le noyau gère le signal d'interruption logicielle reçu par un processus dans le contexte du processus, le processus doit donc être en cours d'exécution. Comme mentionné précédemment lors de l'introduction du concept, il existe trois types de traitement du signal : le processus se termine après avoir reçu le signal ; le processus ignore le signal et après que le processus a reçu le signal, il exécute la fonction définie par l'utilisateur pour appeler le signal ; le système. Lorsqu'un processus reçoit un signal qu'il ignore, il ignore le signal et continue comme si le signal n'avait pas été reçu. Si le processus reçoit un signal à capturer, la fonction définie par l'utilisateur est exécutée lorsque le processus revient du mode noyau au mode utilisateur. De plus, la méthode d'exécution des fonctions définies par l'utilisateur est très intelligente. Le noyau crée une nouvelle couche sur la pile utilisateur, dans cette couche, la valeur de l'adresse de retour est définie sur l'adresse de la fonction de traitement définie par l'utilisateur, de sorte que. lorsque le processus revient du noyau et fait apparaître le haut de la pile, il revient à la fonction définie par l'utilisateur, et lorsqu'il revient de la fonction et fait apparaître le haut de la pile, il revient à l'endroit où il est entré à l'origine dans le noyau. La raison en est que les fonctions de traitement définies par l'utilisateur ne peuvent pas et ne sont pas autorisées à être exécutées en mode noyau (si la fonction définie par l'utilisateur s'exécute en mode noyau, l'utilisateur peut obtenir n'importe quelle autorisation).

Il y a quelques points auxquels il convient de prêter une attention particulière dans la méthode de traitement du signal. Premièrement, dans certains systèmes, lorsqu'un processus gère un signal d'interruption et revient en mode utilisateur, le noyau efface l'adresse de la routine de traitement du signal définie dans la zone utilisateur, c'est-à-dire la prochaine fois que le processus modifie la méthode de traitement du signal. valeur par défaut, sauf si l'appel du système de signalisation est à nouveau utilisé avant l'arrivée du signal suivant. Cela peut amener le processus à obtenir le signal avant d'appeler le signal, ce qui entraîne sa sortie. Sous BSD, le noyau n'efface plus cette adresse. Mais ne pas effacer cette adresse peut amener le processus à recevoir un signal trop rapidement et provoquer un débordement de pile. Afin d'éviter la situation ci-dessus. Dans le système BSD, le noyau simule la méthode de traitement des interruptions matérielles, c'est-à-dire que lors du traitement d'une interruption, il empêche la réception de nouvelles interruptions de ce type.

La deuxième chose à noter est que si le signal à capturer se produit lorsque le processus est dans un appel système et que le processus se met en veille à un niveau de priorité pouvant être interrompu, alors le signal amène le processus à effectuer un longjmp et à sortir du mode veille. state , revenez en mode utilisateur et exécutez la routine de traitement du signal. Au retour d'une routine de gestion de signal, le processus se comporte comme s'il revenait d'un appel système, mais renvoie un code d'erreur indiquant que l'appel système a été interrompu. Il convient de noter que dans les systèmes BSD, le noyau peut redémarrer automatiquement les appels système.

La troisième chose à noter : si le processus dort à un niveau de priorité disruptible, lorsqu'il reçoit un signal à ignorer, le processus est réveillé, mais ne fait pas de longjmp et continue généralement de dormir. Mais l’utilisateur n’a pas l’impression que le processus a été réveillé, mais c’est comme si le signal ne s’était pas produit.

La quatrième chose à noter : la gestion par le noyau du signal de fin de processus enfant (SIGCLD) est différente des autres signaux. Lorsqu'un processus vérifie qu'il a reçu un signal pour terminer un processus enfant, par défaut, le processus agit comme s'il n'avait pas reçu le signal. Si le processus parent exécute l'attente de l'appel système, le processus se réveillera de l'appel système. attendez et revenez à l'appel d'attente, effectuez une série d'opérations de suivi de l'appel d'attente (trouver le processus enfant zombie, libérer l'entrée de la table de processus du processus enfant), puis revenir de l'attente. La fonction du signal SIGCLD est de réveiller un processus endormi à un niveau de priorité disruptible. Si le processus capte le signal, il est transmis à la routine de gestion, tout comme la gestion normale du signal. Si le processus ignore le signal, l'action de l'appel système en attente est différente, car la fonction de SIGCLD est uniquement de réveiller un processus endormi à un niveau de priorité interruption, alors le processus parent qui exécute l'appel en attente est réveillé et continue à exécutez l'appel d'attente. Opérations suivantes, puis attendez les autres processus enfants.

Si un processus appelle l'appel système signal et définit la méthode de traitement SIGCLD, et que le processus a un processus enfant dans un état zombie, le noyau enverra un signal SIGCLD au processus.

2. Les fonctions de setjmp et longjmp

Lors de l'introduction du mécanisme de traitement du signal plus tôt, setjmp et longjmp ont été mentionnés à plusieurs reprises, mais leurs fonctions et méthodes de mise en œuvre n'ont pas été expliquées en détail. Voici une brève introduction à cela.

Lors de l'introduction des signaux, nous avons vu plusieurs endroits exigeant que le processus revienne directement de l'appel système d'origine après avoir vérifié que le signal est reçu, plutôt que d'attendre la fin de l'appel. Cette situation où un processus change soudainement de contexte est le résultat de l'utilisation de setjmp et longjmp. setjmp stocke le contexte enregistré dans la zone utilisateur et continue l'exécution dans l'ancien contexte. C'est-à-dire que le processus exécute un appel système lorsqu'il se met en veille pour des raisons de ressources ou pour d'autres raisons, le noyau effectue un setjmp pour le processus s'il est réveillé par un signal pendant le sommeil et que le processus ne peut pas se rendormir. , le noyau appelle longjmp pour le processus. Cette opération permet au noyau de restaurer le contexte enregistré dans la zone utilisateur du processus par l'appel setjmp d'origine au contexte actuel, afin que le processus puisse revenir à l'état avant d'attendre. pour les ressources, et le noyau renvoie 1 pour setjmp, afin que le processus sache que l'appel système a échoué. C'est ce qu'ils font.

3. Appels système liés aux signaux

La plupart des connaissances sur les signaux ont été introduites dans les deux sections précédentes. Dans cette section, nous découvrirons ces appels système. Parmi eux, le signal d'appel système est utilisé par le processus pour définir la méthode de traitement d'un certain signal, et l'appel système kill est utilisé pour envoyer un signal au processus spécifié. Ces deux appels constituent le fonctionnement de base du signal. Les deux derniers appels, pause et alarme, sont des pauses de processus et des minuteries mises en œuvre via des signaux. L'alarme d'appel est utilisée pour notifier le processus de l'expiration de la minuterie via des signaux. Donc ici, nous présentons également ces deux appels.

1. appel du système de signalisation

Le signal d'appel système est utilisé pour définir la méthode de traitement d'un certain signal. La déclaration d'appel a le format suivant :
void (*signal(int signum, void (*handler)(int)))(int);
Ajoutez le fichier d'en-tête suivant au processus à l'aide de cet appel :
#inclure

Le format de déclaration ci-dessus est relativement compliqué. Si vous ne savez pas comment l'utiliser, vous pouvez également l'utiliser via le format de définition de type suivant (définition POSIX) :
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
Cependant, ce format a différentes définitions de type selon les systèmes, donc pour utiliser ce format, il est préférable de se référer au manuel en ligne.

Dans l'appel, le paramètre signum indique le signal à définir pour gérer la méthode. Le deuxième gestionnaire de paramètres est une fonction de traitement, ou
SIG_IGN : ignore le signal pointé par le paramètre signum.
SIG_DFL : Restaure la méthode de traitement du signal pointé par le paramètre signum à la valeur par défaut.

Le paramètre entier transmis à la routine de traitement du signal est la valeur du signal, ce qui permet à une routine de traitement du signal de traiter plusieurs signaux. La valeur de retour du signal d'appel système est la routine de traitement précédente du signal de signal spécifié ou le code d'erreur SIG_ERR renvoyé en cas d'erreur. Regardons un exemple simple :

#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 (;;) ; 
} 
Copier après la connexion

其中信号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:~$ 
Copier après la connexion

2、kill 系统调用

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

\#include 
\#include 
Copier après la connexion

该 系统调用可以用来向任何进程或进程组发送任何信号。如果参数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 "); 
} 
Copier après la connexion

在这个例子中,程序开始执行,就象进入了死循环一样,这是因为进程正在等待信号,当我们按下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 微秒*/ 
}; 
Copier après la connexion

在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 (;;) ; 
} 
Copier après la connexion

该例子的屏幕拷贝如下:

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
Copier après la connexion

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Impossible de se connecter à MySQL en tant que racine Impossible de se connecter à MySQL en tant que racine Apr 08, 2025 pm 04:54 PM

Les principales raisons pour lesquelles vous ne pouvez pas vous connecter à MySQL en tant que racines sont des problèmes d'autorisation, des erreurs de fichier de configuration, des problèmes de mot de passe incohérents, des problèmes de fichiers de socket ou une interception de pare-feu. La solution comprend: vérifiez si le paramètre Bind-Address dans le fichier de configuration est configuré correctement. Vérifiez si les autorisations de l'utilisateur racine ont été modifiées ou supprimées et réinitialisées. Vérifiez que le mot de passe est précis, y compris les cas et les caractères spéciaux. Vérifiez les paramètres et les chemins d'autorisation du fichier de socket. Vérifiez que le pare-feu bloque les connexions au serveur MySQL.

C compilation conditionnelle du langage: un guide détaillé pour les débutants vers des applications pratiques C compilation conditionnelle du langage: un guide détaillé pour les débutants vers des applications pratiques Apr 04, 2025 am 10:48 AM

C La compilation conditionnelle du langage est un mécanisme pour compiler sélectivement les blocs de code en fonction des conditions de temps de compilation. Les méthodes d'introduction incluent: l'utilisation des directives #IF et #ELSE pour sélectionner des blocs de code en fonction des conditions. Les expressions conditionnelles couramment utilisées incluent STDC, _WIN32 et Linux. Cas pratique: imprimez différents messages en fonction du système d'exploitation. Utilisez différents types de données en fonction du nombre de chiffres du système. Différents fichiers d'en-tête sont pris en charge selon le compilateur. La compilation conditionnelle améliore la portabilité et la flexibilité du code, ce qui le rend adaptable aux modifications du compilateur, du système d'exploitation et de l'architecture du processeur.

Quels sont les 5 composants de base de Linux? Quels sont les 5 composants de base de Linux? Apr 06, 2025 am 12:05 AM

Les cinq composants de base de Linux sont: 1. Le noyau, gérant les ressources matérielles; 2. La bibliothèque système, fournissant des fonctions et des services; 3. Shell, l'interface pour les utilisateurs pour interagir avec le système; 4. Le système de fichiers, stockant et organisant des données; 5. Applications, en utilisant des ressources système pour implémenter les fonctions.

Comment résoudre MySQL ne peut pas être démarré Comment résoudre MySQL ne peut pas être démarré Apr 08, 2025 pm 02:21 PM

Il existe de nombreuses raisons pour lesquelles la startup MySQL échoue, et elle peut être diagnostiquée en vérifiant le journal des erreurs. Les causes courantes incluent les conflits de port (vérifier l'occupation du port et la configuration de modification), les problèmes d'autorisation (vérifier le service exécutant les autorisations des utilisateurs), les erreurs de fichier de configuration (vérifier les paramètres des paramètres), la corruption du répertoire de données (restaurer les données ou reconstruire l'espace de la table), les problèmes d'espace de la table InNODB (vérifier les fichiers IBDATA1), la défaillance du chargement du plug-in (vérification du journal des erreurs). Lors de la résolution de problèmes, vous devez les analyser en fonction du journal d'erreur, trouver la cause profonde du problème et développer l'habitude de sauvegarder régulièrement les données pour prévenir et résoudre des problèmes.

MySQL peut-il fonctionner sur Android MySQL peut-il fonctionner sur Android Apr 08, 2025 pm 05:03 PM

MySQL ne peut pas fonctionner directement sur Android, mais il peut être implémenté indirectement en utilisant les méthodes suivantes: à l'aide de la base de données légère SQLite, qui est construite sur le système Android, ne nécessite pas de serveur distinct et a une petite utilisation des ressources, qui est très adaptée aux applications de périphériques mobiles. Connectez-vous à distance au serveur MySQL et connectez-vous à la base de données MySQL sur le serveur distant via le réseau pour la lecture et l'écriture de données, mais il existe des inconvénients tels que des dépendances de réseau solides, des problèmes de sécurité et des coûts de serveur.

Solutions aux erreurs rapportées par MySQL sur une version système spécifique Solutions aux erreurs rapportées par MySQL sur une version système spécifique Apr 08, 2025 am 11:54 AM

La solution à l'erreur d'installation de MySQL est: 1. Vérifiez soigneusement l'environnement système pour vous assurer que les exigences de la bibliothèque de dépendance MySQL sont satisfaites. Différents systèmes d'exploitation et exigences de version sont différents; 2. Lisez soigneusement le message d'erreur et prenez des mesures correspondantes en fonction des invites (telles que les fichiers de bibliothèque manquants ou les autorisations insuffisantes), telles que l'installation de dépendances ou l'utilisation de commandes sudo; 3. Si nécessaire, essayez d'installer le code source et vérifiez soigneusement le journal de compilation, mais cela nécessite une certaine quantité de connaissances et d'expérience Linux. La clé pour finalement résoudre le problème est de vérifier soigneusement l'environnement du système et les informations d'erreur et de se référer aux documents officiels.

MySQL ne peut pas être installé après le téléchargement MySQL ne peut pas être installé après le téléchargement Apr 08, 2025 am 11:24 AM

Les principales raisons de la défaillance de l'installation de MySQL sont les suivantes: 1. Problèmes d'autorisation, vous devez s'exécuter en tant qu'administrateur ou utiliser la commande sudo; 2. Des dépendances sont manquantes et vous devez installer des packages de développement pertinents; 3. Conflits du port, vous devez fermer le programme qui occupe le port 3306 ou modifier le fichier de configuration; 4. Le package d'installation est corrompu, vous devez télécharger et vérifier l'intégrité; 5. La variable d'environnement est mal configurée et les variables d'environnement doivent être correctement configurées en fonction du système d'exploitation. Résolvez ces problèmes et vérifiez soigneusement chaque étape pour installer avec succès MySQL.

Comment résoudre le problème des dépendances manquantes lors de l'installation de MySQL Comment résoudre le problème des dépendances manquantes lors de l'installation de MySQL Apr 08, 2025 pm 12:00 PM

La défaillance de l'installation de MySQL est généralement causée par le manque de dépendances. Solution: 1. Utilisez System Package Manager (tel que Linux Apt, YUM ou DNF, Windows VisualC Redistribuable) pour installer les bibliothèques de dépendance manquantes, telles que SudoaptInstallLiBMysQlClient-Dev; 2. Vérifiez soigneusement les informations d'erreur et résolvez les dépendances complexes une par une; 3. Assurez-vous que la source du gestionnaire de package est correctement configurée et peut accéder au réseau; 4. Pour Windows, téléchargez et installez les bibliothèques d'exécution nécessaires. Développer l'habitude de lire des documents officiels et de faire bon usage des moteurs de recherche peut résoudre efficacement les problèmes.

See all articles