现在的位置: 首页 > 综合 > 正文

1.9.信号(Signals)

2013年04月27日 ⁄ 综合 ⁄ 共 2642字 ⁄ 字号 评论关闭

1.9.信号(Signals)
信号是通知一个进程已发生某种条件的一种技术(a technique used to notify a process that some condition has occurred)。例如,若某一进程执行除法操作,其除数为0,则名为SIGFPE(浮点数异常floating-point exception)的信号将被发送给该进程。进程如何处理信号有三种选择:
(1) 忽略该信号。对于表示(denote)一个硬件异常的信号,比如除数为0或者访问到了继承的地址空间之外的内存,因为这些异常产生的后果不确定,所以不推荐使用这种处理方式。
(2) 让系统默认行为(default action)进行处理。对于除数为0的情况,系统默认行为是终止该进程。
(3) 提供一个函数,信号发生时则调用该函数(这叫做捕捉信号catch the signal)。使用我们自己提供的函数,我们将能知道什么时候产生了信号,并能按我们所希望的方式处理它。

很多情况下会产生信号。有两种键盘方式,分别称为中断键(interrupt key,通常是DELETE键或Ctrl-C)和退出键(quit key,通常是Ctrl-/),它们被用于中断当前运行的进程。另一种产生信号的方法是调用kill函数。在一个进程中调用此函数就可向另一个进程发送一个信号。当然这种方法也有些限制:当向另一个进程发送信号时,我们必须是该接受信号进程的所有者或者超户。

Example
回忆一下bare-bones shell例子程序(figure1.7)。如果调用此程序,然后键入中断键,则执行此程序的进程终止。产生这种后果的原因是:对于此信号SIGINT的系统默认动作是终止此进程。因为该进程没有告诉kernel对此信号作何处理(即没有按照前述的第三种方法提供一个函数),所以系统按默认方式终止该进程。

为了能捕捉到该信号,figure1.7需要调用signal函数,来指定当SIGINT信号产生时要调用的函数名。因此编写了名为sig_int的函数,当其被调用时,它只是打印一条消息,然后打印一个新提示符。在程序figure1.7中加了11行构成了程序figure1.10(添加的11行以行首的+号指示)。因为大多数重要的应用程序都将使用信号,所以第10章将详细介绍信号。

Figure 1.10. Read commands from standard input and execute them
  #include "apue.h"
  #include <sys/wait.h>

+ static void sig_int(int);       /* our signal-catching function */
+
  int
  main(void)
  {
      char    buf[MAXLINE];    /* from apue.h */
      pid_t   pid;
      int     status;

+     if (signal(SIGINT, sig_int) == SIG_ERR)
+         err_sys("signal error");
+
      printf("%% ");  /* print prompt (printf requires %% to print %) */
      while (fgets(buf, MAXLINE, stdin) != NULL) {
          if (buf[strlen(buf) - 1] == "/n")
              buf[strlen(buf) - 1] = 0; /* replace newline with null */

          if ((pid = fork()) < 0) {
              err_sys("fork error");
          } else if (pid == 0) {        /* child */
              execlp(buf, buf, (char *)0);
              err_ret("couldn't execute: %s", buf);
              exit(127);
          }

          /* parent */
          if ((pid = waitpid(pid, &status, 0)) < 0)
              err_sys("waitpid error");
          printf("%% ");
      }
      exit(0);
  }
+
+ void
+ sig_int(int signo)
+ {
+     printf("interrupt/n%% ");
+ }
-------------------------------------------------------------------
自己写的singa.cpp

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
using namespace std;

#define BUFFSIZE 90

static void sig_int(int);       /* our signal-catching function */

int
main(void)
{
 int n = 0;
 char buf[BUFFSIZE];
     
      if (signal(SIGINT, sig_int) == SIG_ERR)
  cout<<"signal error"<<endl;
 
 
 while( (n = read(STDIN_FILENO,buf,BUFFSIZE)) > 0)
        if (write(STDOUT_FILENO,buf,n) != n)
         cout<<"write error."<<endl;
       exit(0);
}

void
sig_int(int signo)
{
 printf("interrupt/n%% ");
}

[lizl@localhost apue_code]$ ./signal.out
abc
abc
interrupt  键入ctrl-c
dd
dd
% interrupt  键入ctrl-c
% interrupt  键入ctrl-c
% [lizl@localhost apue_code]$  键入ctrl-d
-------------------------------------------------------------------

抱歉!评论已关闭.