Linux系统编程---8(全局变量异步I/O,可重入函数)
生活随笔
收集整理的這篇文章主要介紹了
Linux系统编程---8(全局变量异步I/O,可重入函数)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
全局變量異步 I/O
分析如下父子進程交替 數數 程序。當捕捉函數里面的 sleep 取消,程序即會出現問題。請分析原因。
#include<stdio.h> #include<signal.h> #include<unistd.h> #include<stdlib.h>intn=0,flag=0; void sys_err(char* str) { perror(str); exit(1); } void do_sig_child (int num) {printf("I am child %d\t%d\n",getpid(),n);n+=2;flag=1; sleep(1); } void do_sig_parent (int num) {printf("I am parent%d\t%d\n",getpid(),n);n+=2;flag=1;sleep(1); } int main(void) {pid_tpid; struct sigaction act; if((pid=fork())<0)sys_err("fork");else if(pid>0){n=1;sleep(1);act.sa_handler = do_sig_parent; sigemptyset(&act.sa_mask); act.sa_flags=0;sigaction(SIGUSR2,&act,NULL); //注冊自己的信號捕捉函數 父使用 SIGUSR2 信號 do_sig_parent(0); while(1){ /*waitforsignal*/;if(flag==1){ //父進程數數完成 kill(pid,SIGUSR1);flag=0; //標志已經給子進程發送完信號 } } }else if(pid==0){ n=2;act.sa_handler = do_sig_child; sigemptyset(&act.sa_mask); act.sa_flags=0; sigaction(SIGUSR1,&act,NULL);while(1){ /*waitingforasignal*/;if (flag==1) {kill(getppid(),SIGUSR2); flag=0; } }}return0; }示例中,通過 flag 變量標記程序實行進度。flag 置 1 表示數數完成。flag 置 0 表示給對方發送信號完成。 問題出現的位置,在父子進程 kill 函數之后需要緊接著調用 flag,將其置 0,標記信號已經發送。但,在這期 間很有可能被 kernel 調度,失去執行權利,而對方獲取了執行時間,通過發送信號回調捕捉函數,從而修改了全局 的 flag。
如何解決該問題呢?可以使用后續課程講到的“鎖”機制。當操作全局變量的時候,通過加鎖、解鎖來解決該 問題。
現階段,我們在編程期間如若使用全局變量,應在主觀上注意全局變量的異步 IO 可能造成的問題。
有兩個進程對同一個變量進行操作。
可/不可重入函數
一個函數在被調用執行期間(尚未調用結束),由于某種時序又被重復調用,稱之為“重入”。根據函數實現的方 法可分為“可重入函數”和“不可重入函數”兩種
例如:
顯然,insert 函數是不可重入函數,重入調用,會導致意外結果呈現。究其原因,是該函數內部實現使用了全 局變量。
注意事項
a) 使用靜態數據結構
b) 調用了 malloc 或 free
c) 是標準 I/O 函數
總結
以上是生活随笔為你收集整理的Linux系统编程---8(全局变量异步I/O,可重入函数)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 剑魂85SS板甲护肩听说很屌?
- 下一篇: Linu系统编程---10(Linux的