1. 程式人生 > >系統程式設計函式之訊號量

系統程式設計函式之訊號量

1、設定訊號處理動作:singal NAME        signal - ANSI C signal handling SYNOPSIS    #include <signal.h>    typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); RETURN VALUE        signal() returns the previous value of the signal handler, or SIG_ERR on error.  In the event of an error, errno is set to indicate        the cause. 使用:
void handle(int sig) {     if (SIGINT == sig)     {         printf("catched sigint\n");     } } int main(void) {     //ctrl+c: SIGINT     //設定訊號的處理動作 signal(SIGINT, handle);     while (1)     {         printf("this is main while\n");         sleep(1);     }     return 0; } 2、遮蔽訊號 (1)將訊號新增到訊號組: sigemptyset sigaddset 
NAMEdfsigemptyset, sigfillset, sigaddset, sigdelset, sigismember - POSIX signal set operations SYNOPSIS        #include <signal.h>        int sigemptyset(sigset_t *set);  //清空訊號集合        int sigfillset(sigset_t *set);        int sigaddset(sigset_t *set, int signum);  //新增訊號到集合中        int sigdelset(sigset_t *set, int signum);        int sigismember(const sigset_t *set, int signum); DESCRIPTION        These functions allow the manipulation of POSIX signal sets.        sigemptyset() initializes the signal set given by set to empty, with all signals excluded from the set.        sigfillset() initializes set to full, including all signals.        sigaddset() and sigdelset() add and delete respectively signal signum from set.        sigismember() tests whether signum is a member of set.        Objects of type sigset_t must be initialized by a call to either sigemptyset() or sigfillset() before being passed to the functions        sigaddset(), sigdelset() and sigismember() or the additional glibc functions described  below  (sigisemptyset(),  sigandset(),  and        sigorset()).  The results are undefined if this is not done. RETURN VALUE        sigemptyset(), sigfillset(), sigaddset(), and sigdelset() return 0 on success and -1 on error.        sigismember() returns 1 if signum is a member of set, 0 if signum is not a member, and -1 on error.        On error, these functions set errno to indicate the cause of the error. (2)對訊號組進行設定:sigprocmask
NAME        sigprocmask, rt_sigprocmask - examine and change blocked signals SYNOPSIS        #include <signal.h>    引數2:sigset_t 結構體,訊號集合, 將需要的訊號新增到其中即可        int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);   引數3:訊號之前的狀態 SIG_BLOCK  (阻塞) 也就是上面的引數1:how               The set of blocked signals is the union of the current set and the set argument.        SIG_UNBLOCK (解阻塞)               The signals in set are removed from the current set of blocked signals.  It is permissible to attempt to  unblock  a  signal               which is not blocked.        SIG_SETMASK               The set of blocked signals is set to the argument set. RETURN VALUE        sigprocmask() returns 0 on success and -1 on error.  In the event of an error, errno is set to indicate the cause. 使用: sigset_t set; void handle(int sig) {     //ctrl+c     if (SIGINT == sig)     { #if 0         //若訊號阻塞的操作是在訊號的處理函式中進行的         //則函式結束後,阻塞無效 sigset_t set;         //清空訊號集合   sigemptyset(&set);         //新增SIGTSTP到集合中 sigaddset(&set, SIGTSTP);         //SIG_BLOCK:將訊號集合中的訊號阻塞         //引數三:用來儲存引數二中的訊號之前的狀態         //NULL表示不儲存之前的狀態 sigprocmask(SIG_BLOCK, &set, NULL); #endif         printf("$$$$$$$$$$$$$$$$\n");         int i = 0;         while (1)         {             printf("this is SIGINT handle\n");             sleep(1);             i++;             if (5 == i)             {                 break;             }         }         //若有一個訊號被阻塞但是多次發生         //則解阻塞之後該訊號只會被處理一次   sigprocmask(SIG_UNBLOCK, &set, NULL);     }     else if (SIGTSTP == sig)     {   //ctrl+z         printf("this is SIGTSTP handle\n");     } } int main(void) {    //    sigset_t set;     //清空訊號集合 sigemptyset(&set);     //新增SIGTSTP到集合中   sigaddset(&set, SIGTSTP);   //SIG_BLOCK:將訊號集合中的訊號阻塞     //引數三:用來儲存引數二中的訊號之前的狀態     //NULL表示不儲存之前的狀態 sigprocmask(SIG_BLOCK, &set, NULL);     signal(SIGINT, handle);        signal(SIGTSTP, handle);        while (1)     {         printf("this is main while \n");         sleep(1);     }     return 0; } 3、一個函式完成上面上面兩個功能:sigaction NAME        sigaction, rt_sigaction - examine and change a signal action SYNOPSIS        #include <signal.h>        int sigaction(int signum, const struct sigaction *act,       引數1:要處理的訊號 引數2:通過結構體對訊號進行  struct sigaction *oldact);                                      引數3:保留之前的處理方式,不想保留設定為:NULL            struct sigaction {                void     (*sa_handler)(int);                   void     (*sa_sigaction)(int, siginfo_t *, void *);                sigset_t   sa_mask;  //訊號集合,                int        sa_flags;  //配置                void     (*sa_restorer)(void);            };            SA_NOCLDSTOP  flags: 若訊號是SIGCHLD,處理過程中不處理其他訊號                   If  signum  is  SIGCHLD,  do not receive notification when child processes stop (i.e., when they receive one of SIGSTOP,                   SIGTSTP, SIGTTIN, or SIGTTOU) or resume (i.e., they receive SIGCONT) (see wait(2)).  This flag is meaningful  only  when                   establishing a handler for SIGCHLD.            SA_NOCLDWAIT (since Linux 2.6)                   If  signum  is  SIGCHLD, do not transform children into zombies when they terminate.  See also waitpid(2).  This flag is                   meaningful only when establishing a handler for SIGCHLD, or when setting that signal's disposition to SIG_DFL.                   If the SA_NOCLDWAIT flag is set when establishing a handler for SIGCHLD, POSIX.1 leaves it unspecified whether a SIGCHLD                   signal  is  generated  when  a  child process terminates.  On Linux, a SIGCHLD signal is generated in this case; on some                   other implementations, it is not.            SA_NODEFER  //處理A A再次發生 不阻塞A                   Do not prevent the signal from being received from within its own signal handler.  This flag  is  meaningful  only  when                   establishing a signal handler.  SA_NOMASK is an obsolete, nonstandard synonym for this flag.            SA_ONSTACK                     Call  the  signal  handler on an alternate signal stack provided by sigaltstack(2).  If an alternate stack is not avail‐                  able, the default stack will be used.  This flag is meaningful only when establishing a signal handler.            SA_RESETHAND  //當訊號發生時呼叫特殊函式處理,處理完按預設方式處理,僅執行一次                   Restore the signal action to the default upon entry to the signal handler.  This flag is meaningful only when establish‐                   ing a signal handler.  SA_ONESHOT is an obsolete, nonstandard synonym for this flag.            SA_RESTART                   Provide  behavior  compatible with BSD signal semantics by making certain system calls restartable across signals.  This                   flag is meaningful only when establishing a signal handler.  See signal(7) for a discussion of system call restarting.            SA_RESTORER                   Not intended for application use.  This flag is used by C libraries to indicate that the sa_restorer field contains  the                  address of a "signal trampoline".  See sigreturn(2) for more details.            SA_SIGINFO (since Linux 2.2)                   The  signal  handler  takes  three  arguments, not one.  In this case, sa_sigaction should be set instead of sa_handler.                   This flag is meaningful only when establishing a signal handler. RETURN VALUE        sigaction() returns 0 on success; on error, -1 is returned, and errno is set to indicate the error. 使用: void handle(int sig) {     if (SIGINT == sig)     {         printf("$$$$$$$$$$$$$$$$\n");         int i = 0;         while (1)         {             printf("this is SIGINT handle\n");             sleep(1);             i++;             if (5 == i)             {                 break;             }         }     }     else if (SIGTSTP == sig)     {       //ctrl+z         printf("this is SIGTSTP handle\n");     } } int main(void) {    struct sigaction act; act.sa_handler = handle; sigemptyset(&(act.sa_mask)); sigaddset(&(act.sa_mask), SIGTSTP);   //通過結構體同時設定某個訊號的處理函式和需要遮蔽的訊號集 sigaction(SIGINT, &act, NULL);     struct sigaction act2;     act2.sa_handler = handle;     sigaction(SIGTSTP, &act2, NULL);     while (1)     {         printf("this is main while \n");         sleep(1);     }     return 0; } 1、訊號的建立:sem_init   (一般用於執行緒同步) NAME        sem_init - initialize an unnamed semaphore SYNOPSIS        #include <semaphore.h> 引數1:要初始化的訊號量 2:設定該訊號量用於        int sem_init(sem_t *sem, int pshared, unsigned int value); //初始化訊號量  引數1:要初始化的訊號量                                                                                                            Link with -pthread.                                                    //引數2:設定該訊號量用於程序間同步還是用於執行緒間同步  //0:表示用於執行緒間  //非0:表示用於程序間 RETURN VALUE                                                              //引數3:訊號量的整數值,代表資源的可用數        sem_init() returns 0 on success; on error, -1 is returned, and errno is set to indicate the error. 2、訊號的等待:sem_wait NAME        sem_wait, sem_timedwait, sem_trywait - lock a semaphore SYNOPSIS        #include <semaphore.h>        int sem_wait(sem_t *sem);  //等於0等待        int sem_trywait(sem_t *sem);   //等於0不等待,去做其他事        int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); //等於0,等待指定之間,然後去做其他事 3、通知等待某訊號的執行緒:sem_post  將訊號量加1 NAME        sem_post - unlock a semaphore SYNOPSIS        #include <semaphore.h>        int sem_post(sem_t *sem);        Link with -pthread. RETURN VALUE        sem_post() returns 0 on success; on error, the value of the semaphore is left unchanged, -1 is returned, and errno is set to  indi‐        cate the error.
1、訊號量的建立semget     //建立訊號量集合     //引數一:使用一個十六進位制的整數作為該集合的名字     //        名字可以重複     //引數二: 設定該集合中訊號量的個數     //IPC_CREAT|0664:建立集合並指定操作許可權     //成功返回該集合的識別符號,     //通過識別符號來唯一確定集合     semid = semget(0x1024, NUM, IPC_CREAT|0664); 2、對訊號量的設定semop 1)建立訊號集 semid = semget。。 semid = semget(0x1024, NUM, IPC_CREAT|0664); 2)定義結構體 struct sembuf sem     int left = num;     int right = (num+1)%NUM;     struct sembuf sem[2] = {{left, -1, 0}                             , {right, -1, 0}}; 3)//通過結構體指定的操作來操作集合中的訊號量 semop(semid, sem, 2); 引數1:訊號集識別符號, 引數2:
sops:指向進行操作的訊號量集結構體陣列的首地址,此結構的具體說明如下: struct sembuf {     short semnum; /*訊號量集合中的訊號量編號,0代表第1個訊號量*/     short val;/*若val>0進行V操作訊號量值加val,表示程序釋放控制的資源 */ /*若val<0進行P操作訊號量值減val,若(semval-val)<0(semval為該訊號量值),則呼叫程序阻塞,直到資源可用;若設定IPC_NOWAIT不會睡眠,程序直接返回EAGAIN錯誤*/   /*若val==0時阻塞等待訊號量為0,呼叫程序進入睡眠狀態,直到訊號值為0;若設定IPC_NOWAIT,程序不會睡眠,直接返回EAGAIN錯誤*/     short flag;  /*0 設定訊號量的預設操作*/ /*IPC_NOWAIT設定訊號量操作不等待*/ /*SEM_UNDO 選項會讓核心記錄一個與呼叫程序相關的UNDO記錄,如果該程序崩潰,則根據這個程序的UNDO記錄自動恢復相應訊號量的計數值*/   };
引數3:進行操作訊號量的個數,即sops結構變數的個數,需大於或等於1。最常見設定此值等於1,只完成對一個訊號量的操作 返回:訊號集識別符號 3、設定集合中訊號量的值:semctl         //引數一:集合識別符號         //引數二:集合中第幾個訊號量         //引數三:對集合的操作命令         //    SETVAL:對訊號量賦值         //引數四:根據命令傳入不定個數的資料         semctl(semid, i, SETVAL, sem);    1) semid = semget(0x1024, NUM, IPC_CREAT|0664); 2)定義聯合體 union semun sem union semun {     int val;     struct semid_ds *buf;     unsigned short  *array;     struct seminfo  *__buf; };     union semun sem;     sem.val = 1; 3)設定集合中訊號量的值:semctl         semctl(semid, i, SETVAL, sem); 使用: pthread_mutex_t pmutex; pthread_mutex_t gmutex; union semun {     int val;     struct semid_ds *buf;     unsigned short  *array;     struct seminfo  *__buf; }; #define NUM 5//用來儲存訊號量集合的識別符號 int semid = -1;//獲得筷子 void getChopsticks(int num) {     int left = num;     int right = (num+1)%NUM;     //成員一:操作集合中第幾個訊號量     //成員二:-1表示獲得資源,1表示釋放資源     //成員三:0表示若資源不滿足則阻塞等待直到滿足為止     struct sembuf sem[2] = {{left, -1, 0}                             , {right, -1, 0}};     //通過結構體指定的操作來操作集合中的訊號量     semop(semid, sem, 2); } //放下筷子 void putChopsticks(int num) {     int left = num;     int right = (num+1)%NUM;     //成員一:操作集合中第幾個訊號量     //成員二:-1表示獲得資源,1表示釋放資源     //成員三:0表示若資源不滿足則阻塞等待直到滿足為止     struct sembuf sem[2] = {{left, 1, 0}                             , {right, 1, 0}};     //通過結構體指定的操作來操作集合中的訊號量     semop(semid, sem, 2); } void *run(void *arg) {     int num = (int)arg;     while (1)     {         printf("第%d個哲學家正在思考...\n", num+1);         sleep(1);         //獲得筷子吃飯         pthread_mutex_lock(&gmutex);         getChopsticks(num);         printf("第%d個哲學家獲得筷子吃飯...\n", num+1);         pthread_mutex_unlock(&gmutex);         sleep(1);         pthread_mutex_lock(&pmutex);         putChopsticks(num);         printf("第%d個哲學家放下筷子...\n", num+1);         pthread_mutex_unlock(&pmutex);         sleep(1);     } } int main(void) {     int i = 0;     //建立訊號量集合     //引數一:使用一個十六進位制的整數作為該集合的名字     //        名字可以重複     //引數二: 設定該集合中訊號量的個數     //IPC_CREAT|0664:建立集合並指定操作許可權     //成功返回該集合的識別符號,     //通過識別符號來唯一確定集合     semid = semget(0x1024, NUM, IPC_CREAT|0664); union semun sem;     sem.val = 1;     for (i = 0; i < NUM; i++)     {         //設定集合中訊號量的值         //引數一:集合識別符號         //引數二:集合中第幾個訊號量         //引數三:對集合的操作命令         //    SETVAL:對訊號量賦值         //引數四:根據命令傳入不定個數的資料         semctl(semid, i, SETVAL, sem);     }     pthread_t thr[NUM];     //建立五個哲學家執行緒     for (i=0; i<NUM; i++)     {         pthread_create(thr+i, NULL, run, (void*)i);     }     //等待執行緒結束     for (i=0; i<NUM; i++)     {         pthread_join(thr[i], NULL);     }     return 0; }

相關推薦

系統程式設計函式訊號

1、設定訊號處理動作:singal NAME        signal - ANSI C signal handling SYNOPSIS    #include <signal.h>    typedef void (*sighandler_t)(int); sighandler_t

系統程式設計函式程序及程序通訊

1、產生一個子程序 NAME        fork - create a child process SYNOPSIS        #include <unistd.h>        pid_t fork(void); RETURN VALUE      

linux下c程式設計訊號semget,semop,semctl函式

訊號量 今天去參加北京市的植樹志願者活動啦!早上起來的挺早的,6:10就被傑子給叫起來啦,帶著對春天的嚮往,我們坐著不花錢的大巴去做為市領導服務去啦!發了一個小紅帽還有一個紅色的制服。 唉。。。說好

4.IPC訊號 //依據RT-Thread核心程式設計的學習記錄(非核心實現)

IPC: Inter proess communication   大的任務中的各任務資訊互動配合,內容包括訊號量,互斥鎖,訊號,訊息佇列,郵箱     本篇文章,只討論第一個內容,訊號量 1.訊號量的建立 和執行緒的建立方式類似,訊號量的建立也分動態dynamic和靜態

21.Linux/Unix 系統程式設計手冊(上) -- 訊號訊號處理器函式

1.可重入函式 如果同一個程序的多條執行緒可以同時安全的呼叫某一函式,那麼該函式就是可重入的。 2.非同步訊號安全函式 指當訊號處理函式呼叫時,可以保證其實現是安全的。如果某一函式是可重入的,又或者 訊號處理函式無法將其中斷,就稱該函式是非同步訊號函式. 3.全域

Python並行程式設計(五):執行緒同步訊號

1、基本概念       訊號量是由作業系統管理的一種抽象資料型別,用於在多執行緒中同步對共享資源的使用。本質上說,訊號量是一個內部資料,用於標明當前的共享資源可以有多少併發讀取。       同樣在threading中,訊號量有acquire和release兩個函式。       - 每當執行緒想要讀取關聯

《java併發程式設計實戰》:執行緒同步輔助類訊號(semaphore)

1.訊號量的概念: 訊號量是一種計數器,用來保護一個或者多個共享資源的訪問,它是併發程式設計的一種基礎工具,大多數程式語言都提供了這個機制。 2、訊號量控制執行緒訪問流程: 如果執行緒要訪問一個共享資源,它必須先獲得訊號量。如果訊號量的內部計數器大於0,訊號量將減1,然後

linux系統——IPC程序通訊訊號

一、訊號量引出 當我們編寫的程式使用執行緒的時候,總是有一部分臨街程式碼,需要確保只有一個程序(或一個執行緒)可以進入這個臨街程式碼並擁有對資源的獨佔式訪問 ——》檔案鎖,提供了一個原子化的檔案建立方法,它允許一個程序通過一個令牌(新建立的檔案)來取得成功,這個

linux 多執行緒訊號 sem_init

1. 什麼是訊號量 linux sem 訊號量是一種特殊的變數,訪問具有原子性, 用於解決程序或執行緒間共享資源引發的同步問題。 使用者態程序對 sem 訊號量可以有以下兩種操作: 等待訊號量 當訊號量值為 0 時,程式等待;當訊號量值大於 0 時,訊號量減 1,程式

C語言嵌入式系統程式設計修煉

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Java併發程式設計(8)-Semaphore訊號解讀

文章目錄 一、Semaphore訊號量 1.1、什麼是訊號量 1.2、訊號量在併發程式設計中的作用 二、Semaphore類簡單解讀 2.1、構造方法解讀

Java併發程式設計實戰————Semaphore訊號的使用淺析

引言 本篇部落格講解《Java併發程式設計實戰》中的同步工具類:訊號量 的使用和理解。 從概念、含義入手,突出重點,配以程式碼例項及講解,並以生活中的案例做類比加強記憶。 什麼是訊號量 Java中的同步工具類訊號量即計數訊號量(Counting Semaphore),是

Linux訊號

訊號量概念 Dijkstra提出的“訊號量”概念是共發程式設計領域的一項重大進步 訊號量是一種變數,它只能取正整數值,對這些正整數只能進行兩種操作:等待和訊號 用兩種記號來表示訊號量的這兩種操作:     P(semaphore variable) 代表等待     V(s

linux程序控制訊號 semget,semctl,semop

轉載自 https://www.cnblogs.com/52php/p/5851570.html 這篇文章將講述別一種程序間通訊的機制——訊號量。注意請不要把它與之前所說的訊號混淆起來,訊號與訊號量是不同的兩種事物。有關訊號的更多內容,可以閱讀我的另一篇文章:L

Alios things學習訊號與互斥

Sem訊號量  1. 概念 任務可以通過獲取訊號量來獲取訪問共享資源的“門禁”,可以通過配置訊號量數目,讓多個任務同時獲取門禁,當無法獲取時,任務會按照優先順序排隊獲取“門禁”,缺點是存在優先順序翻轉問題。  2. sem操作      1)靜態建立:kstat

Java執行緒訊號

 計數訊號量用來控制同時訪問某個特定資源的運算元量,或者同時執行某個指定操作的數量。計數訊號量還可以用來實現某種資源池,或者對容器施加邊界。  Semaphore中管理者一組虛擬的許可,許可的數量可通過建構函式來指定。在互相操作時可以首先獲得許可(只要還有剩餘的許可),並在使用以後釋放許可。

併發程式設計-concurrent指南-訊號Semaphore

Semaphore翻譯成字面意思為 訊號量,Semaphore可以控同時訪問的執行緒個數,通過 acquire() 獲取一個許可,如果沒有就等待,而 release() 釋放一個許可。 acquire()用來獲取一個許可,若無許可能夠獲得,則會一直等待,直到獲得許可。 release()用來釋放許可。注意

多執行緒訊號Semaphore及原理

一、訊號量(Semaphore) 重入鎖ReentrantLock是獨佔模式,一次都只允許一個執行緒訪問一個資源,而訊號量是共享模式,也就是說可以指定多個執行緒,同時訪問某一個資源。 Semaphore的兩個構造方法: public Semaphore(int pe

linux多執行緒程式設計(C):訊號實現的執行緒安全佇列

用訊號量實現的執行緒安全佇列。 簡單有用的示例程式, 比起互斥量的實現在多執行緒時效率更好。 cir_queue.h /* * \File * cir_queue.h * \Brief * circular queue */#ifndef __CIR_QUEUE_H_

Linux操作系統基礎操作的相關設置

數字 info 雙引號 bsp 不能 直接 本地變量 用戶 環境 Bash變量分類環境變量特殊變量(系統變量) 預定義變量 位置變量用戶變量(本地變量)用戶變量在編程過程中使用最多系統變量在對參數判斷和命令返回值判斷使用環境變量主要是在程序運行的時候需要設置 查看變量