日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux 信号可靠性,同步,异步,多线程信号等介绍

發布時間:2024/10/12 linux 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux 信号可靠性,同步,异步,多线程信号等介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

鑒于網上超多關于Linux信號處理相關的文章,本篇關于基本的信號知識不再普及,只提出一些平時不常關注或者關注不到的一些方面:

1. 信號可靠性:此可靠指的是信號是否會排隊,并不是指信號會丟失(其實在也可以理解為不排隊的信號就會丟失)。SIGRTMIN以下的信號不會被排隊處理,即只傳遞一次,如果進程已經有信號還未被處理,后面再來同樣的信號即丟失,其他的不同信號還是進入排隊處理。SIGRTMIN以上的信號,都會進入隊列

2. 信號異步處理:進程注冊的信號處理函數將在進程內核態返回用戶態時被調用,相對于進程主線程或其他線程來說,是并行處理的

3. 信號同步處理:進程可以選擇以同步的方式來處理信號,比如由一個特定的線程來處理

4. 多線程中的信號:對于內核來說,沒有進程與線程的區分,所有都是進程;對于進程來說,所有線程共享進程地址空間,包括注冊的信號,即子線程會繼承主線程所注冊的信號環境

5. 誰來執行信號處理函數:異步處理時由最小號的線程來處理;同步處理時由用戶特定的調用同步函數的線程來執行

6. 誰可以注冊信號:誰都可以注冊,主線程子線程都可以;注冊與處理不是相關聯的

7. 在多個地方注冊信號了處理函數,將怎么處理:信號處理函數將以最后調用的信號注冊函數為準

關于信號API:

異步處理 sigaction:

void sig_handler(int signum) {... }struct sigaction action; memset(&action, 0, sizeof(action)); action.sa_handler = sig_handler; sigemptyset(&action.sa_mask); action.sa_flags = 0; /* restart property */ action.sa_flags |= SA_RESTART; sigaction(SIGUSR2, &action, NULL);

同步處理 sigwaitinfo:

void* sub_sig_handle_thread() {sigset_t waitset, oset;siginfo_t info;int rc;pthread_t ppid = pthread_self();pthread_detach(ppid);sigemptyset(&waitset);sigaddset(&waitset, SIGRTMIN);sigaddset(&waitset, SIGUSR1);while (1) {rc = sigwaitinfo(&waitset, &info);if (rc != -1) {printf("<--sigwaitinfo() fetch the signal %d\n", rc);sig_handler(info.si_signo);} else {printf("<--sigwaitinfo() return err: %d; %s\n", errno, strerror(errno));}} }

在某個獨立的線程中,循環調用sigwaitinfo檢測是否有未處理的信號,有則主動調用信號處理函數

多線程信號繼承:

1. 每個線程都有自己獨立的signal mask,但所有線程共享進程的signal action

2. 主線程調用pthread_sigmask創建信號屏蔽策略,將被所有子線程繼承

3. pthread_kill 發送的目的線程需要與調用線程再同一個進程之中

4. 跨進程發送信號使用kill 指定進程PID

5. 同步處理時,子線程sigaddset的信號必須是主線程sigaddset的子集

同步、異步處理共存:

1. 同樣的信號同時都被同步異步所注冊,同步優先級更高,將以同步方式處理

2. 不同信號可以被不同方式處理,比如同步處理SIGUSR1的同時可以異步處理SIGUSR2

測試例程:

#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <pthread.h> #include <unistd.h> #include <sys/types.h>#define MUTIL_THREAD 1void sig_handler(int signum) {static int j = 0;static int k = 0;pthread_t sig_ppid = pthread_self(); // used to show which thread the signal is handled in.printf("<-- get sig %d\n", signum);if (signum == SIGUSR1) {printf("<--thread %ld, receive SIGUSR1 No. %d\n", sig_ppid, j);j++;//SIGRTMIN should not be considered constants from userland, //there is compile error when use switch case} else if (signum == SIGRTMIN) {printf("<--thread %ld, receive SIGRTMIN No. %d\n", sig_ppid, k);k++;} else if (signum == SIGUSR2) {printf("<--thread %ld, receive SIGUSR2\n", sig_ppid);} }void* worker_thread() {pthread_t ppid = pthread_self();pthread_detach(ppid);int ret = 0;struct timeval tv = {10, 0}; //10swhile (1) {printf("I'm thread %ld, I'm alive\n", ppid);tv.tv_sec = 10;ret = select(0, NULL, NULL, NULL, &tv);if(ret < 0)printf("thread %ld interrupt by signal\n", ppid);//sleep(10);} }void* sigmgr_thread() {sigset_t waitset, oset;siginfo_t info;int rc;pthread_t ppid = pthread_self();pthread_detach(ppid);#if MUTIL_THREADsigemptyset(&waitset);sigaddset(&waitset, SIGRTMIN);sigaddset(&waitset, SIGUSR1); #elsestruct sigaction action;memset(&action, 0, sizeof(action)); action.sa_handler = sig_handler;sigemptyset(&action.sa_mask);action.sa_flags = 0;/* restart property */action.sa_flags |= SA_RESTART;sigaction(SIGUSR2, &action, NULL); #endifwhile (1) {rc = sigwaitinfo(&waitset, &info);if (rc != -1) {printf("<--sigwaitinfo() fetch the signal %d\n", rc);sig_handler(info.si_signo);} else {printf("<--sigwaitinfo() return err: %d; %s\n", errno, strerror(errno));}} }int main() {sigset_t bset, oset;int i;pid_t pid = getpid();pthread_t ppid[7];struct sigaction action;memset(&action, 0, sizeof(action)); action.sa_handler = sig_handler;sigemptyset(&action.sa_mask);action.sa_flags = 0;/* restart property */action.sa_flags |= SA_RESTART;#if MUTIL_THREADsigaddset(&action.sa_mask, SIGRTMIN);sigaddset(&action.sa_mask, SIGUSR1); //handle by sub-thread // sigaddset(&action.sa_mask, SIGUSR2);if(pthread_sigmask(SIG_BLOCK, &action.sa_mask, &oset) != 0)printf("!! Set pthread mask failed\n");sigaction(SIGUSR2, &action, NULL); //handle by main #elsesigaction(SIGUSR1, &action, NULL);sigaction(SIGRTMIN, &action, NULL); //only main #endifprintf("main pid %d, %ld\n", pid, pthread_self());// Create the dedicated thread sigmgr_thread() which will handle // SIGUSR1 and SIGRTMIN synchronouslypthread_create(&ppid[0], NULL, sigmgr_thread, NULL);// Create 5 worker threads, which will inherit the thread mask of// the creator main threadfor (i = 0; i < 5; i++) {pthread_create(&ppid[i+1], NULL, worker_thread, NULL);}//wait sub-thread to regist signalsleep(3);// send out 50 SIGUSR1 and SIGRTMIN signalsfor (i = 0; i < 5; i++) {printf("\n-->main thread, send SIGUSR1 No. %d\n", i);kill(pid, SIGUSR1);printf("-->main thread, send SIGRTMIN No. %d\n", i);kill(pid, SIGRTMIN);printf("-->main thread, send SIGUSR2 No. %d\n", i);kill(pid, SIGUSR2);sleep(1);}struct timeval tv = {50, 0};int ret = select(0, NULL, NULL, NULL, &tv);if(ret < 0)printf("main interrupt by signal\n");return 0; }

運行結果:

main pid 12018, 140114995099392
I'm thread 140114978449152, I'm alive
I'm thread 140114970056448, I'm alive
I'm thread 140114953271040, I'm alive
I'm thread 140114944878336, I'm alive
I'm thread 140114961663744, I'm alive

-->main thread, send SIGUSR1 No. 0
-->main thread, send SIGRTMIN No. 0
-->main thread, send SIGUSR2 No. 0
<-- get sig 12
<--thread 140114995099392, receive SIGUSR2??? --->主線程處理USR2
<--sigwaitinfo() fetch the signal 10
<-- get sig 10
<--thread 140114986841856, receive SIGUSR1 No. 0?? -->同步處理信號
<--sigwaitinfo() fetch the signal 34
<-- get sig 34
<--thread 140114986841856, receive SIGRTMIN No. 0?? -->同步處理信號

-->main thread, send SIGUSR1 No. 1
-->main thread, send SIGRTMIN No. 1
-->main thread, send SIGUSR2 No. 1
<--sigwaitinfo() fetch the signal 10
<-- get sig 10
<--thread 140114986841856, receive SIGUSR1 No. 1
<--sigwaitinfo() fetch the signal 34
<-- get sig 34
<--thread 140114986841856, receive SIGRTMIN No. 1
<-- get sig 12
<--thread 140114995099392, receive SIGUSR2

總結

以上是生活随笔為你收集整理的Linux 信号可靠性,同步,异步,多线程信号等介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。