国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 操作系統 > 正文

信號之system函數

2024-06-28 13:28:26
字體:
來源:轉載
供稿:網友
信號之system函數

在http://www.CUOXin.com/nufangrensheng/p/3512291.html中已經有了一個system函數的實現,但是該版本并不執行任何信號處理。POSIX.1要求system忽略SIGINT和SIGQUIT,阻塞SIGCHLD。

實例

程序清單10-19使用http://www.CUOXin.com/nufangrensheng/p/3512291.html中的system版本,用其調用ed(1)編輯器。(ed很久以來就是UNIX的組成部分。在這里調用它的原因是:它是捕捉中斷和退出信號的交互式程序。若 從shell調用ed,并鍵入中斷字符,則它捕捉中斷信號并打印問號。它還將對退出符的處理方式設置為忽略。

程序清單10-19 用system調用ed編輯器

#include "apue.h"static voidsig_int(int signo){    PRintf("caught SIGINT/n");}static voidsig_chld(int signo){    printf("caught SIGCHLD/n");}intmain(void){    if(signal(SIGINT, sig_int) == SIG_ERR)        err_sys("signal(SIGINT) error");    if(signal(SIGCHLD, sig_chld) == SIG_ERR)        err_sys("signal(SIGCHLD) error");    if(system("/bin/ed") < 0)        err_sys("system() error");    exit(0);}

程序清單10-19用于捕捉SIGINT和SIGCHLD信號。若調用它則可得:

未命名 

當編輯器終止時,系統向父進程(a.out進程)發送SIGCHLD信號。父進程捕捉它,然后從信號處理程序返回。但是若父進程正在捕捉SIGCHLD信號(因為它創建了子進程,所以應當這樣做以便了解它的子進程在何時終止),那么正在執行system函數時,應當阻塞對父進程遞送SIGCHLD信號。實際上,這就是POSIX.1所說明的。否則,當system創建的子進程結束時,system的調用者可能錯誤地認為,它自己的一個子進程結束了。于是,調用者將會調用一種wait函數以獲得子進程的終止狀態,這樣就阻止了system函數獲得子進程的終止狀態,并將其作為它的返回值。

如果再次執行該程序,在這次運行時將一個中斷信號傳送給編輯器,則可得:

未命名

鍵入中斷字符可使中斷信號傳送給前臺進程組中的所有進程。編輯程序正在運行時的各個進程的關系:

  登錄shell ---fork/exec---> a.out ---fork/exec---> /bin/sh ---fork/exec---> /bin/ed

  后臺進程組                                                        前臺進程組

a.out ---fork/exec---> /bin/sh 是由a.out中調用system函數引起的:http://www.CUOXin.com/nufangrensheng/p/3512291.html

/bin/sh ---fork/exec---> /bin/ed 可參考類shell程序的簡化實現程序清單1-5:http://www.CUOXin.com/nufangrensheng/p/3495129.html

在這一實例中,SIGINT被送給三個前臺進程(shell進程忽略此信號)。從輸出中可見a.out進程和ed進程捕捉該信號。但是,當用system運行另一程序(例如ed)時,不應使父子進程兩者都捕捉中斷產生的兩個信號:中斷和退出。這兩個信號只應送給正在運行的程序:子進程。因為由system執行的命令可能是交互式命令(例如本例中的ed程序),以及因為system的調用者在程序執行時放棄了控制,等待該執行程序的結束,所以system的調用者就不應接收這兩個終端產生的信號。這就是為什么POSIX.1規定system的調用者應當忽略這兩個信號的原因。(糊里糊涂的感覺)

實例

程序清單10-20 system函數的POSIX.1正確實現

#include <sys/wait.h>#include <errno.h>#include <signal.h>#include <unistd.h>intsystem(const char *cmdstring)    /* with appropriate signal handling */{    pid_t             pid;        int            status;    struct sigaction    ignore, saveintr, savequit;    sigset_t        chldmask, savemask;    if(cmdstring == NULL)        return(1);    /* always a command processor with UNIX */        ignore.sa_handler = SIG_IGN;    /* ignore SIGINT and SIGQUIT */    sigemptyset(&ignore.sa_mask);    ignore.sa_flags = 0;    if(sigaction(SIGINT, &ignore, &saveintr) < 0)        return(-1);    if(sigaction(SIGQUIT, &ignore, &savequit) < 0)        return(-1);    sigemptyset(&chldmask);        /* now block SIGCHLD */    sigaddset(&chldmask, SIGCHLD);    if(sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0)        return(-1);    if((pid = fork()) < 0)    {        status = -1;    /* probably out of processes */    }    else if(pid == 0)    {        /* restore previous signal actions & reset signal mask */        sigaction(SIGINT, &saveintr, NULL);        sigaction(SIGQUIT, &savequit, NULL);        sigprocmask(SIG_SETMASK, &savemask, NULL);         /* 在父進程中忽略SIGINT,SIGQUIT,阻塞SIGCHLD,在子進程中恢復 */        execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);        _exit(127);    /* exec error */     }    else    {        while(waitpid(pid, &status, 0) < 0)            if(errno != EINTR)            {                status = -1; /* error other than EINTR from waitpid() */                break;            }    }    /* restore previous signal actions & reset signal mask */    if(sigaction(SIGINT, &saveintr, NULL) < 0)        return(-1);    if(sigaction(SIGQUIT, &savequit, NULL) < 0)        return(-1);    if(sigprocmask(SIG_SETMASK, &savemask, NULL) < 0)        return(-1);                                           /* 子進程退出后,父進程才恢復SIGINT,SIGQUIT和SIGCHLD */    return(status);}

如果鏈接程序清單10-19與system函數的這一實現,那么所產生的二進制代碼與上一個有缺陷的程序相比較,存在如下差別:

(1)當我們鍵入中斷或退出字符時,不向調用者進程發送信號。

(2)當ed命令終止時,不向調用進程發送SIGCHLD信號。作為替代,在程序末尾的sigprocmask調用對SIGCHLD信號解除阻塞之前,SIGCHLD信號一直被阻塞。而對sigprocmask函數的這一次調用是在system函數調用waitpid取到子進程的終止狀態之后。

 

system的返回值

注意system的返回值,它是shell的終止狀態,但shell的終止狀態并不總是執行命令字符串進程的終止狀態。

Bourne shell有一個在其文檔中沒有說清楚的特性:當用一個信號終止了正在執行的命令時,其終止狀態是128加上一個信號編號

用交互方式使用shell可以看到這一點:

未命名

在所使用的系統中,SIGINT的值為2,SIGQUIT的值為3,于是給出shell終止狀態130、131.

僅當shell本身異常終止時,system的返回值才報告一個異常終止。

在編寫使用system函數的程序時,一定要正確地解釋返回值。如果直接調用fork、exec和wait,則終止狀態與調用system是不同的

 

本篇博文內容摘自《UNIX環境高級編程》(第二版),僅作個人學習記錄所用。關于本書可參考:http://www.apuebook.com/


上一篇:信號之sleep函數

下一篇:信號之abort函數

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 咸丰县| 安丘市| 磴口县| 武强县| 阿鲁科尔沁旗| 石楼县| 革吉县| 龙山县| 梧州市| 库尔勒市| 德阳市| 仁寿县| 大名县| 安康市| 连平县| 乡城县| 陆丰市| 辽阳县| 承德市| 龙川县| 大方县| 定兴县| 太保市| 江北区| 沙湾县| 奉化市| 饶阳县| 聊城市| 屯门区| 内丘县| 弥渡县| 杨浦区| 鹿泉市| 正蓝旗| 鹤壁市| 唐山市| 孙吴县| 鱼台县| 邵阳县| 永济市| 新晃|