xiaosuo@gentux test $ gcc -g -rdynamic f.c
xiaosuo@gentux test $ ./a.out
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".
Attaching to program: /home/xiaosuo/test/a.out, process 9563
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
0xffffe410 in __kernel_vsyscall ()
(gdb) bt
#0 0xffffe410 in __kernel_vsyscall ()
#1 0xb7ee4b53 in waitpid () from /lib/libc.so.6
#2 0xb7e925c9 in strtold_l () from /lib/libc.so.6
现在说说对上面话的理解: 我认为函数或进程的运行最终都回归结尾系统调用,(呵呵,非官方,自己理解) 那么 “进程正在执行某个系统调用,那么在该系统调用返回前信号是不会被递送的”,就是说大多数进程在运行期间是阻塞信号的,系统调用完再处理, 但是(以下引用APUE):如果在进程执行一个低速系统而阻塞期间捕捉到一个信号,该系统调用被终端不再继续执行 When a system call is slow and a signal arrives while it was blocked,waiting for something, the call is aborted and returns -EINTR ,so that the library function will return -1 and set errno to EINTR . Just before the system call returns, the user program'ssignal handler is called. (So, what is "slow"? Mostly those calls that can block forever waitingfor external events; read and write to terminal devices, but notread and write to disk devices, wait , pause .) This means that a system call can return an error while nothing waswrong. Usually one will want to redo the system call. That can beautomated by installing the signal handler using a call to sigaction with the SA_RESTART flag set.The effect is that upon an interrupt the system call is aborted,the user program's signal handler is called, and afterwardsthe system call is restarted from the beginning. 我们可以选择使用循环再次调用,或者设置重新启动该系统调用(SA_RESTART), 这是是低速系统调用被信号中断的解决办法,1循环2SA——RESTART 好啦,实验代码: #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9
10 void int_handler (int signum)
11 {
12 printf ("int handler %d/n",signum);
13 }
14
15 int main(int argc, char **argv)
16 {
17 char buf[100];
18 ssize_t ret;
19 struct sigaction oldact;
20 struct sigaction act;
21
22 act.sa_handler = int_handler;
23 act.sa_flags=0;
24 act.sa_flags |= SA_RESTART;
25 sigemptyset(&act.sa_mask);
26 if (-1 == sigaction(SIGINT,&act,&oldact))
27 {
28 printf("sigaction failed!/n");
29 return -1;
30 }
31
32 bzero(buf,100);
33
34 ret = read(STDIN_FILENO,buf,10);
35 if (ret == -1)
36 {
37 printf ("read error %s/n", strerror(errn o)); 38 }
39 printf ("read %d bytes, content is %s/n",ret,buf );
40 sleep (10);
41 return 0;
42 } 这里我们就看第二种解决办法SA—restart 运行看结果: ^Cint handler 2
^Cint handler 2
^Cint handler 2
^Cint handler 2
^Cint handler 2
^Cint handler 2
hgfd
read 5 bytes, content is hgfd
^Cint handler 2 现在说说对上面话的理解: 我认为函数或进程的运行最终都回归结尾系统调用,(呵呵,非官方,自己理解) 那么 “进程正在执行某个系统调用,那么在该系统调用返回前信号是不会被递送的”,就是说大多数进程在运行期间是阻塞信号的,系统调用完再处理, 但是(以下引用APUE):如果在进程执行一个低速系统而阻塞期间捕捉到一个信号,该系统调用被终端不再继续执行 When a system call is slow and a signal arrives while it was blocked,waiting for something, the call is aborted and returns -EINTR ,so that the library function will return -1 and set errno to EINTR . Just before the system call returns, the user program'ssignal handler is called. (So, what is "slow"? Mostly those calls that can block forever waitingfor external events; read and write to terminal devices, but notread and write to disk devices, wait , pause .) This means that a system call can return an error while nothing waswrong. Usually one will want to redo the system call. That can beautomated by installing the signal handler using a call to sigaction with the SA_RESTART flag set.The effect is that upon an interrupt the system call is aborted,the user program's signal handler is called, and afterwardsthe system call is restarted from the beginning. 我们可以选择使用循环再次调用,或者设置重新启动该系统调用(SA_RESTART), 这是是低速系统调用被信号中断的解决办法,1循环2SA——RESTART 好啦,实验代码: #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9
10 void int_handler (int signum)
11 {
12 printf ("int handler %d/n",signum);
13 }
14
15 int main(int argc, char **argv)
16 {
17 char buf[100];
18 ssize_t ret;
19 struct sigaction oldact;
20 struct sigaction act;
21
22 act.sa_handler = int_handler;
23 act.sa_flags=0;
24 act.sa_flags |= SA_RESTART;
25 sigemptyset(&act.sa_mask);
26 if (-1 == sigaction(SIGINT,&act,&oldact))
27 {
28 printf("sigaction failed!/n");
29 return -1;
30 }
31
32 bzero(buf,100);
33
34 ret = read(STDIN_FILENO,buf,10);
35 if (ret == -1)
36 {
37 printf ("read error %s/n", strerror(errn o)); 38 }
39 printf ("read %d bytes, content is %s/n",ret,buf );
40 sleep (10);
41 return 0;
42 } 这里我们就看第二种解决办法SA—restart 运行看结果: ^Cint handler 2
^Cint handler 2
^Cint handler 2
^Cint handler 2
^Cint handler 2
^Cint handler 2
hgfd
read 5 bytes, content is hgfd
^Cint handler 2
在程序read之前不要输入,ctrl+c这样不会中断read输入后主程序就向下运行啦,这样就不在低速的系统调用即read中啦,所以再次ctrl+c结束; 下面改程序:把程序24行注释掉:结果 ^Cint handler 2
read error Interrupted system call
read -1 bytes, content is
程序立即结束啦, 但我们和第一次相比也观察到很奇怪的结果
根据结果 比较,其实是第二次运行是把ctrl+c读入,而第一次就是运行啦信号处理函数,不把ctrl+c作为READ的读入,
在程序read之前不要输入,ctrl+c这样不会中断read输入后主程序就向下运行啦,这样就不在低速的系统调用即read中啦,所以再次ctrl+c结束; 下面改程序:把程序24行注释掉:结果 ^Cint handler 2
read error Interrupted system call
read -1 bytes, content is
程序立即结束啦, 但我们和第一次相比也观察到很奇怪的结果
根据结果 比较,其实是第二次运行是把ctrl+c读入,而第一次就是运行啦信号处理函数,不把ctrl+c作为READ的读入,
#3 0x08048830 in dump (signo=11) at f.c:22
#4
#5 0x0804884c in dummy_function () at f.c:31
#6 0x08048886 in main () at f.c:38 |