system for signal

来源:互联网 发布:网络维护外包收费标准 编辑:程序博客网 时间:2024/06/05 16:33

comments: 交互式程序ed的使用和图前台shell组是看点。

要求system忽略SIGINT和SIGQUIT,阻塞SIGCHLD。

        程序清单10-19使用8.13节中的system版本,用其调用ed(1)编辑器。这里调用ed的原因是:它是捕捉中断和退出信号的交互式程序。若从shell调用ed,并键入中断字符,则它捕捉中断信号并打印问号。它还将退出符的处理方式设置为忽略。

        《UNIX环境高级编程》P276:程序清单10-19 用system调用ed编辑器(有改动)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h>
 
int system(const char *command);
 
static void sig_int(int signo)
{
    printf("caught SIGINT\n");
}
 
static void sig_chld(int signo)
{
    printf("caught SIGCHLD\n");
}
 
int main(void)
{
    if (signal(SIGINT, sig_int) == SIG_ERR)
        fprintf(stderr, "signal(SIGINT) error\n");
 
    if (signal(SIGCHLD, sig_chld) == SIG_ERR)
        fprintf(stderr, "signal(SIGCHLD) error\n");
 
    if (system("/bin/ed") < 0)
        fprintf(stderr, "system() error\n");
 
    exit(0);
}
 
int system(const char *command)
{
    pid_t   pid;
    int     status;
 
    if (command == NULL)
        return(1);              // UNIX中system总是可用的
 
    if ((pid = fork()) < 0) {
        status = -1;            // 进程创建出错
    else if (pid == 0) {      // 子进程
        execl("/bin/sh""sh""-c", command, (char *)0);
        _exit(127);
    else {                    // 父进程
        while (waitpid(pid, &status, 0) < 0) {
            if (errno != EINTR) {
                status = -1;    // 除了EINTR之外的出错
                break;
            }
        }
    }   
 
    return status;
}

        程序清单10-19用于捕捉SIGINT和SIGCHLD信号。若调用它则可得:

?
1
2
3
4
5
6
7
8
9
10
$ ./19
a                               将正文添加至编辑器缓冲区
Here is one line of text
.                               行首的点停止添加方式
1,$p                            打印缓冲区的第1行至最后1行 
Here is one line of text
w temp.foo                      将缓冲区写至一个文件
25                              编辑器称写了25个字符
q                               离开编辑器
caught SIGCHLD

        当编辑器终止时,系统向父进程发送SIGCHLD信号。父进程捕捉它,然后从信号处理程序返回。但是若父进程正在捕捉SIGCHLD信号,那么正在执行system函数时,应当阻塞对父进程递送SIGCHLD信号。否则,当system创建的子进程结束时,system的调用者可能错误地认为,它自己的一个子进程结束了。于是,调用者将会调用一种wait函数以获得子进程的终止状态,这样就阻止了system函数获得子进程的终止状态,并将其作为它的返回值。

        如果再次执行该程序,在这次运行时将一个中断信号传送给编辑器,则可得:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
$ ./19
a                   将正文添加至编辑器缓冲区
hello, world
.                   行首的点停止添加方式
1,$p                打印缓冲区中的第1行至最后1行 
hello, world
w temp.foo          将缓冲区写至一个文件
13                  编辑器称写了13个字节
^C                  键入中断符(Ctrl+C)
?                   编辑器捕捉信号,打印问号
caught SIGINT       父进程执行同一操作
q                   离开编辑器
caught SIGCHLD

        键入中断字符可使中断信号传送给前台进程组中的所有进程。如图所示,显示了编辑程序正在运行时的各个进程的关系:

                        

        在这一实例中,SIGINT被送给三个前台进程(shell进程忽略此信号)。从输出可见,./19进程和ed进程捕捉该信号。但是,当用system运行另一个程序(如ed)时,不应使父、子进程两者都捕捉终端产生的两个信号:中断和退出。这两个信号只应送给正在运行的程序:子进程。因为由system执行的控制命令可能是交互式命令,以及因为system的调用者在执行程序时放弃了控制,等待该执行程序的结束,所以system的调用者就不应接收这两个终端产生的信号

0 0
原创粉丝点击