六、信号捕捉
1.内核是如何捕捉信号的:
如果信号的处理动作是用户自定义的,那么这个信号递达的时就会调用这个函数,称为信号捕捉。下图阐述了 捕捉信号 的过程:
sigaction()函数可以捕捉信号。
#include<signal.h>
int sigaction(int signo,const struct sigaction *act,struct sigaction *oact);
参数:1.信号名 或编号。2.结构体
strutct sigaction
{
void (*sa_handler)(int);//捕捉函数地址
sigset_t sa_mask;
int sa_flags;
void (*sa_sigaction)(int, siginfo_t*,void*)
};
pause
#include<unistd.h>
int pause(void);
pause函数使调用进程挂起直到有信号递达。如果信号的处理动作是终止进程,则进程终
⽌止,pause函数没有机会返回;如果信号的处理动作是忽略,则进程继续处于挂起状态,pause
不返回;如果信号的处理动作是捕捉,则调用了信号处理函数之后pause返回-1,errno设置为
EINTR, 所以pause只有出错的返回值。错误码EINTR表示“被信号中断”。
可以用已知的alarm闹钟和pause函数,实现sleep函数的功能。
#include<stdio.h>
#include<signal.h>
void myhandler(int sig)
{
}
int mysleep(int timeout)
{
struct sigaction act,oact;
act.sa_handler=myhandler;//注册信号处理函数
sigemptyset(&act.sa_mask);
act.sa_flags=0;
sigaction(SIGALRM,&act,&oact);
alarm(timeout);//设置闹钟
pause();//挂起到其他操作
int ret=alarm();//
sigaction(SIGALRM,&oact,NULL);//恢复默认处理动作
}
int main()
{
while(1)
{
mysleep(5);
printf("using mysleep!\n");
}
return 0;
}
[root@localhost code6-6]#
七、线程安全问题
1.线程安全问题:当用线程编写程序时,必须小心地编写那些具有称为线程安全性(thread safety)属性的函数。多线程访问运行时,当一个线程访问数据时采用加锁机制,对数据进行保护,保证了数据不会出现错乱。
2.产生线程不安全的原因:多线程程序对全局变量或者静态变量进行修改。
3.确保线程安全:要确保线程安全,首先要考虑到线程之间的共享数据。属于同一进程的不同线程只有自己独有的私有栈与寄存器,公共分享占有堆与全局区,因此对于一般进程中的线程之间,局部变量是私有的,而静态局部变量,全局变量,分配在堆上的数据时共有的,因此针对这些数据的操作需要进行加密。
可重入函数:
当程序在执行一个函数过程中,收到信号,则立即停止对该函数的执行,并且恰好程序收到的信号为执行该函数,这就完成了所谓的重入,如果该函数此时能正常的运行,并且在执行结束后,之前暂停的函数还能运行下去,则称为该函数是可重入函数。
可重入函数是线程安全函数。