当前位置: 技术问答>linux和unix
请问在程序中调用signal()进行注册的时候,注册的过程是怎样实现的
来源: 互联网 发布时间:2016-02-27
本文导语: 最近在看linux0.11,有这么个问题,希望大家解答。 我想问的是在程序中出现signal()函数的时候,是不是仅仅只是注册这个函数,而当程序往下执行而发出信号的时候,这个时候才发生int0x80中断从而进行调用sys_signal和d...
最近在看linux0.11,有这么个问题,希望大家解答。
我想问的是在程序中出现signal()函数的时候,是不是仅仅只是注册这个函数,而当程序往下执行而发出信号的时候,这个时候才发生int0x80中断从而进行调用sys_signal和do_signal函数?另外,注册这个过程是怎样实现的?
为了表述的更清晰一些,我在网上找了个例子来说明,如下:
int main()
{
/* 进程号 */
pid_t pid;
/* 想用信号?那先对信号处理函数进行注册,对应起来 */
signal(SIGCHLD, handler);
/* 程序在这里“分叉”,新的进程创建了 */
pid = fork();
/* 通过fork()的返回值来判断是父进程还是子进程 */
switch(pid){
/* 返回 -1,很不幸,创建进程失败了。可能是没有足够的内存空间,也可能已经开起了太多的进程。 */
case -1:
perror("forkn");
break;
/* 返回 0,现在是在子进程里运行,那就调用子进程的操作函数。 */
case 0:
/* 一个运行65535次的循环,如果你的机子太快,不能看清楚两个进程同时运行的效果,那就再加大循环次数。或用sleep()函数 */
big_loop(FAC_N);
/* 取得子进程的PID,你可以看清楚子进程和父进程的PID是不同的(子进程的PID比父进程的要大,因为是在父进程运行后才创建的)。*/
printf("PID:%dn", getpid());
/* 子进程执行完了,发送信号 SIGCHLD。由于前面对这个信号进行了注册,这时就会转入信号处理操作。 */
break;
/* 哈哈,返回的即不是错误,又不是子进程,那就是父进程喽。*/
default:
/* 这里让用户输入了4个数 */
input_information();
/* 取得子进程的PID。*/
printf("PID:%dn", getpid());
break;
}
exit(0);
}
请问是不是在
/* 想用信号?那先对信号处理函数进行注册,对应起来 */
signal(SIGCHLD, handler);
这里的时候还没有进行int0x80的系统调用,这里仅仅是注册?那注册如何实现和完成的?
而在
/* 子进程执行完了,发送信号 SIGCHLD。由于前面对这个信号进行了注册,这时就会转入信号处理操作。 */
这个地方才触发了真正的signal的系统调用的?
非常希望大家能回答我的问题,不甚感激
我想问的是在程序中出现signal()函数的时候,是不是仅仅只是注册这个函数,而当程序往下执行而发出信号的时候,这个时候才发生int0x80中断从而进行调用sys_signal和do_signal函数?另外,注册这个过程是怎样实现的?
为了表述的更清晰一些,我在网上找了个例子来说明,如下:
int main()
{
/* 进程号 */
pid_t pid;
/* 想用信号?那先对信号处理函数进行注册,对应起来 */
signal(SIGCHLD, handler);
/* 程序在这里“分叉”,新的进程创建了 */
pid = fork();
/* 通过fork()的返回值来判断是父进程还是子进程 */
switch(pid){
/* 返回 -1,很不幸,创建进程失败了。可能是没有足够的内存空间,也可能已经开起了太多的进程。 */
case -1:
perror("forkn");
break;
/* 返回 0,现在是在子进程里运行,那就调用子进程的操作函数。 */
case 0:
/* 一个运行65535次的循环,如果你的机子太快,不能看清楚两个进程同时运行的效果,那就再加大循环次数。或用sleep()函数 */
big_loop(FAC_N);
/* 取得子进程的PID,你可以看清楚子进程和父进程的PID是不同的(子进程的PID比父进程的要大,因为是在父进程运行后才创建的)。*/
printf("PID:%dn", getpid());
/* 子进程执行完了,发送信号 SIGCHLD。由于前面对这个信号进行了注册,这时就会转入信号处理操作。 */
break;
/* 哈哈,返回的即不是错误,又不是子进程,那就是父进程喽。*/
default:
/* 这里让用户输入了4个数 */
input_information();
/* 取得子进程的PID。*/
printf("PID:%dn", getpid());
break;
}
exit(0);
}
请问是不是在
/* 想用信号?那先对信号处理函数进行注册,对应起来 */
signal(SIGCHLD, handler);
这里的时候还没有进行int0x80的系统调用,这里仅仅是注册?那注册如何实现和完成的?
而在
/* 子进程执行完了,发送信号 SIGCHLD。由于前面对这个信号进行了注册,这时就会转入信号处理操作。 */
这个地方才触发了真正的signal的系统调用的?
非常希望大家能回答我的问题,不甚感激
|
按我的理解,用户态的signal()执行后会调用核态的sys_signal(),并把信号处理函数以及其他信息添加到当前进程的struct task_struct的sigaction[]中,此时不会触发实际的信号处理函数。
信号的处理的一个很重要的入口在system_call.s的ret_from_sys_call(系统调用返回时)中,在发现有信号pending(且未被block)时,此时会调用do_signal(),将信号处理函数插入到用户态堆栈中,在系统调用返回后会立即执行信号处理函数。
信号的处理的一个很重要的入口在system_call.s的ret_from_sys_call(系统调用返回时)中,在发现有信号pending(且未被block)时,此时会调用do_signal(),将信号处理函数插入到用户态堆栈中,在系统调用返回后会立即执行信号处理函数。
|
1). 首先signal就是int 0x80实现的,没有更多的功能,就是添加进程的signal_handler
2). Linux属于内核非抢占调度,也就是说内核态不主动让出CPU,schedule没有办法切换进程的,只能在用户态抢占(通过中断/异常进入内核态并完成重新调度的)
3). 信号的处理是在从内核态到用户态切换之前完成的,比如中断/系统调用处理完毕之前:此时为了返回用户态的寄存器(这是由int 0x80导致的并保存在内核态堆栈的),会调用ret_from_intr/ret_from_syscall/ret_from_exception, 这三个函数都会检查有没有pending的signal,如果有,就调用do_signal(),当然这比较复杂,因为signal_handler属于用户态的空间,所以内核要在user->stack上面建立frame,然后再回到内核态,最终返回系统调用/异常。
4). pending signal是由发送方调用kill(),这个系统调用同样进入内核态,找到信号的收者,并把这个信号添加到接受者进程的signals,并且如果不被blocked,设置pending signal标志。这样接受者进程如果有机会得到执行,从内核态回来之前肯定会发现这个信号的,转到3执行就好了。
==========================
aria(*nix learner)说得对
up
2). Linux属于内核非抢占调度,也就是说内核态不主动让出CPU,schedule没有办法切换进程的,只能在用户态抢占(通过中断/异常进入内核态并完成重新调度的)
3). 信号的处理是在从内核态到用户态切换之前完成的,比如中断/系统调用处理完毕之前:此时为了返回用户态的寄存器(这是由int 0x80导致的并保存在内核态堆栈的),会调用ret_from_intr/ret_from_syscall/ret_from_exception, 这三个函数都会检查有没有pending的signal,如果有,就调用do_signal(),当然这比较复杂,因为signal_handler属于用户态的空间,所以内核要在user->stack上面建立frame,然后再回到内核态,最终返回系统调用/异常。
4). pending signal是由发送方调用kill(),这个系统调用同样进入内核态,找到信号的收者,并把这个信号添加到接受者进程的signals,并且如果不被blocked,设置pending signal标志。这样接受者进程如果有机会得到执行,从内核态回来之前肯定会发现这个信号的,转到3执行就好了。
==========================
aria(*nix learner)说得对
up
|
分三步
第一步,注册信号处理函数,这个过程要在内核中记录处理函数的地址
第二步,其它进程或内核或自己递送信号,其实也是在内核中作个标记,意思是说发生了某个信号
第三步,从系统返回用户空间之前执行信号处理程序
第一步,注册信号处理函数,这个过程要在内核中记录处理函数的地址
第二步,其它进程或内核或自己递送信号,其实也是在内核中作个标记,意思是说发生了某个信号
第三步,从系统返回用户空间之前执行信号处理程序