3.4、Unix/Linux体系结构、信号编程初步
2019-04-01 本文已影响0人
奥斯特洛司机
1、Unix/Linux操作系统体系结构
类Unix操作系统体系结构分为两个状态,用户态和内核态以及硬件
a)操作系统/内核:用来控制计算机硬件资源,提供应用程序运行的环境
我们写程序,会运行在用户态和内核态之一,一般来讲是运行在用户态的,当程序执行一些特殊代码的时候,程序就可能切换到内核态,这种切换由操作系统控制,不需要人为控制。
b)系统调用:就是一些系统库函数
c)shell:bash: login通过fork出来的子进程,是shell的一种。主要作用是把用户输入的命令翻译给操作系统,是一个命令解释器。
d)用户态和内核态之间的切换:
运行与用户态的进程可以执行的操作或者访问的资源会收到极大限制,权限小。
内核态的进程可以执行任何操作并在资源上的使用没有限制。
这种转换是操作系统干的,通过系统调用,或者异常事件收到信号(也叫软中断),或者外围设备中断,不需要程序员介入。
为什么要区分用户态和内核态?一是:权限小不至于危害到系统其它部分。
二是:通过操作系统统一管理的系统调用接口,达到操作的安全性。资源是有限的,如果不加以管理,容易造成使用资源冲突。资源耗尽还会引起系统崩溃。
2、signal函数范例
参照:https://www.jianshu.com/p/021336717366
进程收到信号,就会被内核注意到,内核知道进程有没有信号处理函数,
这里注意图片上传:
2.1、可重入函数
在信号处理函数中保证调用函数是安全的就叫可重入函数。并被成为异步信号安全的。malloc,printf不可重入,errno。
在信号处理函数中写代码要注意的事项:
1)只使用简单的语句做简单的事情,精良不要调用系统函数。
2)如果必须要在信号处理函数中调用系统函数,那么要保证在信号处理函数中调用的系统函数是可冲入的。
3)如果必须要在信号处理函数中调用那些可能修改errno值的可重入的系统函数,事先就得备份errno值,从信号处理函数返回之前将errno值恢复。
int myerrno = errno;进入设置
errno = myerrno; 退出设置
系统调用函数中可重入函数列表上图:
2.2、不可重入函数的错用演示
malloc 因为信号处理函数malloc的存在,可能free的时候释放的不是这个malloc开辟的地址。 一旦在信号处理函数中使用了不可重入的函数,会导致不可预料的错乱
signal因为兼容性,可靠性等一些历史问题,不建议使用,建议使用sigaction()函数代替。坚决不用signal。高手主动回避。
void sig_usr(int signum){
int*p; //导致错乱了三行代码
p=(int*)malloc(sizeof(int)); //
free(p); //
if(signum == SIGUSR1){
printf("SIGUSR1");
}
else if(signum == SIGUSR2){
printf("SIGUSR2");
}
else{
printf("other signal");
}
}
int main (void){
if(signal(SIGUSR1, sig_usr) == SIG_ERR){
printf("signal");
}
if(signal(SIGUSR2, sig_usr) == SIG_ERR){
printf("signal");
}
for(;;){
int*p;
p=(int*)malloc(sizeof(int));
free(p);
}
return 0;
}