linux内核——内核信号量

Posted 西邮菜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux内核——内核信号量相关的知识,希望对你有一定的参考价值。

需要解决的问题:

1、系统中什么是信号、有什么信号?

2、系统接收到信号,如何处理?

3、信号的作用。

一、linux内核中的信号

#define SIGHUP		 1
#define SIGINT		 2
#define SIGQUIT		 3
#define SIGILL		 4
#define SIGTRAP		 5
#define SIGABRT		 6
#define SIGIOT		 6
#define SIGUNUSED	 7
#define SIGFPE		 8
#define SIGKILL		 9
#define SIGUSR1		10
#define SIGSEGV		11
#define SIGUSR2		12
#define SIGPIPE		13
#define SIGALRM		14
#define SIGTERM		15
#define SIGSTKFLT	16
#define SIGCHLD		17
#define SIGCONT		18
#define SIGSTOP		19
#define SIGTSTP		20
#define SIGTTIN		21
#define SIGTTOU		22

二、系统如何调用接受的信号与作用 

        do_signal函数是内核系统调用中断(int 0X80)中断处理子程序的预处理程序,该函数的主要作用是将信号的处理句柄插入到用户程序堆栈中,系统调用后就会执行

        sys_signal由函数库提供,用于恢复系统调用后的返回值和一些寄存器。编译链接时由libc函数库提供,用于 在信号处理程序结束后清理用户态堆栈,并恢复系统调用存放在eax中的返回值。

        信号作用:信号是进程间通信的简单的消息,信号虽然不带任何信息。但是子进程结束后他会产生一个17信号给父进程,显示子进程当前的状态。信号处理函数会被压入用户堆栈 。

三、信号处理的流程

在system_call.s中,可以看到首先调用的是do_signal进行预处理,再调用sys_signal信号处理 。

call sys_call_table(,%eax,4)        # 间接调用指定功能C函数
	pushl %eax                          # 把系统调用返回值入栈




incl %ecx                       # 将信号调整为从1开始的数(1-32)
	pushl %ecx                      # 信号值入栈作为调用do_signal的参数之一
	call do_signal                  # 调用C函数信号处理程序(kernel/signal.c)
	popl %eax                       # 弹出入栈的信号值
3:	popl %eax                       # eax中含有上面入栈系统调用的返回值
	popl %ebx
	popl %ecx
	popl %edx
	pop %fs
	pop %es
	pop %ds
	iret

        3.1 do_signal

        由于C函数是传值函数,因此给eip赋值时需要使用'*(&eip)'的形式。

         3.2 sys_signal

        signal()系统调用。类似于sigaction()。为指定的信号安装新的信号句柄(信号处理程序)。 信号句柄可以是用户指定的函数,也可以是SIG_DFL(默认句柄)或SIG_IGN(忽略)。参数signum --指定的信号;handler --指定的句柄;restorer --恢复函数指针,该函数由Libc库提供。用于在信号处理程序结束后恢复系统调用返回时几个寄存器的原有值以及系统 调用的返回值,就好像系统调用没有执行过信号处理程序而直接返回到用户程序一样。 函数返回原信号句柄。

int sys_signal(int signum, long handler, long restorer)

	设置分配一个信号结构体
	struct sigaction tmp;
	检索信号范围要在1-32并且不是终止信号			
	if (signum<1 || signum>32 || signum==SIGKILL)
		return -1;
	指定信号处理句柄
	tmp.sa_handler = (void (*)(int)) handler;
	设置屏蔽码
	tmp.sa_mask = 0;
	设置改信号的状态为只可执行一次就恢复到默认值 
	tmp.sa_flags = SA_ONESHOT | SA_NOMASK;
	保存回复处理程序指针
	tmp.sa_restorer = (void (*)(void)) restorer;
	更新当先标识指针的信号信息
	handler = (long) current->sigaction[signum-1].sa_handler;
current->sigaction[signum-1] = tmp;
	return handler;

注意:

        当一个子进程终止或结束时都给父进程发送一个标号为17的SIGCHLD信号,用来通知父进程子进程的当前状态。

以上是关于linux内核——内核信号量的主要内容,如果未能解决你的问题,请参考以下文章

内核中 subsys_initcall 以及初始化标号

linux内核 —— 读写信号量实验

Linux内核参数信号量semaphore设置

linux 内核信号量

精通内核Linux 内核写锁实现原理与源码解析

Linux 内核同步之自旋锁与信号量的异同