首页 > 系统相关 >《Unix&Linux系统编程》第六章学习笔记

《Unix&Linux系统编程》第六章学习笔记

时间:2022-10-30 13:55:06浏览次数:45  
标签:printf int 编程 pid 中断 Unix 信号 Linux 进程

第6章 信号和信号处理

6.1 信号和中断

中断是从I/O设备或协处理器发送到CPU的外部请求,将CPU从正常执行转移到中断处理。信号是发送给进程的请求,将进程从正常执行转移到中断处理。
(1)人员中断
人员的每个动作函数都是通过本能或经验实现的,每个中断都分配由一个唯一的ID识别号和一个预先安装的动作函数,人在收到中断请求时“执行”动作函数。

  • 来自硬件的中断
  • 来自其他人的中断
  • 自己造成的中断
  • 不可屏蔽(NMI)
  • 可屏蔽

(2)进程中断
每个进程中断都被转换为一个唯一ID号,发送给进程。Unix/Linux中的进程中断成为信号,编号为1—31.进程也可屏蔽某些类型的信号以推迟处理,必要时可能修改信号动作函数。

  • 来自硬件的中断:终端、间隔定时器的“^C”组合键等。
  • 来自其他进程的中断:kill(pid,SIG#)、death_of_child等。
  • 自己造成的中断:除以0、无效地址等。

(3)硬件中断
每个中断都有唯一的中断向量号。CPU不会导致任何自己造成的中断(除非出错)。

  • 来自硬件的中断:定时器、I/O设备等。
  • 来自其他处理器的中断:FFP、DMA、多处理器系统中的其他CPU。
  • 自己造成的中断:除以0、保护错误、INT指令。

(4)进程的陷阱错误
进程可能会自己造成中断,是由被CPU识别为异常的错误引起的(除以0、无效地址、非法指令、越权……),它会陷入操作系统内核,将陷阱原因转换为信号编号发送给自己。

6.2 Unix/Linux信号示例

  • Ctrl+C组合键:转换为SIGINT(2)信号,发送给终端,终止当前运行的进程。进程对大多数信号的默认操作是调用内核的kexit(exitValue)函数来终止。
  • 用户可使用nohup a.out命令在后台运行程序,nohup会使sh复刻子进程来执行程序,但子进程会忽略SIGNUP(1)信号。
  • 通过ps -u LTD发现后台进程仍在运行,可使用kill pid (or kill -s 9 pid)杀死进程。执行杀死的进程向pid标识的目标进程发送一个SIGTERM(15)信号,请求它死亡。
    如果进程忽略该信号,可能拒绝死亡,可以使用kill -s 9 pid必能杀死。

6.3 Unix/Linux中的信号处理

1.信号类型

Unix/Linux支持31种不同的信号,每种信号在signal.h文件中都有定义,每种信号都有一个符号名。

2.信号来源

  • 来自硬件中断的信号
    中断健(Ctrl+C)产生一个SIGINT(2)信号
    间隔定时器:SIGALRM(14)、SIGVTALRM(26)或SIGPROF(27)
    其他硬件错误:总线错误、I/O陷阱等
  • 来自异常的信号
    SIGFPE(8):浮点异常(除以0)
    SIGSEGV(11):段错误
  • 来自其他进程的信号
    可使用kill(pid,sig)系统调用向pid标识的目标进程发送信号。

3.安装信号捕捉函数

进程可使用系统调用:

int r = signal(int signal_number, void *handler);

来修改选定信号编号的处理函数。

6.4 信号处理步骤

  • 处于内核模式会检查思念好并处理未完成的信号。
  • 重置用户安装的信号捕捉函数
  • 信号和唤醒

6.5 信号与异常

  • 进程遇到异常,会陷入内核模式。若在内核模式下发生异常,则打印一条PANIC错误信息并停止;若在用户模式下发生异常,则终止并以内存转储进行调试。
  • 让进程通过预先安装的信号捕捉函数处理用户模式下的程序错误。
  • 特殊情况下,会让某个进程通过信号杀死另一个进程。

6.6 Linux中的IPC

  • 管道和FIFO
  • 信号
  • System V IPC
  • POSIX消息队列
  • 线程同步机制
  • 套接字

实践内容

1、段错误捕捉函数

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#include<setjmp.h>
jmp_buf env;
int count = 0;
void handler(int sig,siginfo_t *siginfo,void *context)
{
	printf("handler:sig=&d from PID=%d UID=%d count=%d\n",sig,siginfo->si_pid,siginfo->si_uid,++count);
	if (count>=4)
		longjmp(env,1234);
}
int BAD()
{
	int *ip=0;
	printf("in BAD():try to dereference NULL pointer\n");
	*ip=123;
	printf("should not see this line\n");
}
int main(int argc,char *argv[])
{
	int r;
	struct sigaction act;
	memset (&act,0,sizeof(act));
	act.sa_sigaction = &handler;
	act.sa_flags=SA_SIGINFO;
	sigaction(SIGSEGV, &act,NULL);
	if((r=setjmp(env))==0)
		BAD();
	else
		printf("proc %d survived SEGMENTATION FAULT:r=%d\n",getpid(),r);
	printf("proc %d looping\n");
	while(1);
}

2、实现一个消息IPC

#include<stdio.h>
#include<signal.h>
#include<string.h>
#define LEN 64
int ppipe[2];
int pid;
char line[LEN];
int parent()
{
	printf("parent %d running\n",getpid());
	close(ppipe[0]);
	while(1){
		printf("parent %d: input a line : \n",getpid());
		fgets(line,LEN,stdin);
		line[strlen(line)-1]=0;
		printf("parent %d write to pipe\n",getpid());
		write(ppipe[1],line,LEN);
		printf("parent %d send signal 10 to %d\n",getpid(),pid);
		kill(pid,SIGUSR1);
	}
}
void chandler(int sig)
{
	printf("\nchild %d got an interrupt sig=%d\n",getpid(),sig);
	read(ppipe[0],line,LEN);
	printf("child %d get a message = %s\n",getpid(),line);
}
int child()
{
	char msg[LEN];
	int parent = getppid();
	printf("child %d running\n",getpid());
	close(ppipe[1]);
	signal(SIGUSR1,chandler);
	while(1);
}
int main()
{
	pipe(ppipe);
	pid=fork();
    if(pid) parent();
	else child();
}

标签:printf,int,编程,pid,中断,Unix,信号,Linux,进程
From: https://www.cnblogs.com/weihehahaha/p/16841137.html

相关文章

  • 《Unix/Linux系统编程》第六章学习笔记
    第6章信号和信号处理摘要本章讲述了信号和信号处理;介绍了信号和中断的统一处理,有助于从正确的角度看待信号;将信号视为进程中断,将进程从正常执行转移到信号处理;解释了信......
  • windows 2003 oracle 10.2.0.4 升级迁移到linux 11.2.0.4
    文档课题:windows2003oracle10.2.0.4升级迁移到linux11.2.0.4源端:windows200332位+oracle10.2.0.432位+双实例目标端:centos7.964位+oracle11.2.0.464位应......
  • .net core独立部署到Linux问题点总结
    1.修改配置文件:将所有路径改成Linux下的路径;如果使用了log4net,记得修改日志保存路径;2.发布时选择独立部署、目标运行时选择Linux;3.如是是用mysql,记得在etc/my.cnf的配置......
  • Linux学习笔记之mac系统Vmware Fusion虚拟机黑屏问题
    vmwarefusion虚拟机黑屏mac详细参考此文,​​https://zhuanlan.zhihu.com/p/108613520​​目前在MontereyMacOS12.6系统测试适用,仅做记录在此/*......
  • 学习ASP.NET Core Blazor编程系列九——服务器端校验
    学习ASP.NETCoreBlazor编程系列一——综述学习ASP.NETCoreBlazor编程系列二——第一个Blazor应用程序(上)学习ASP.NETCoreBlazor编程系列二——第一个Blazor应......
  • Linux:RedHat8 联网安装docker
    1.查看docker版本安装yum-config-manager#这个命令在yum-utils包yuminstall-yyum-utils下载docker-ce的源#下载docker-ce源文件yum-config-manager--add-repohttps:/......
  • Linux:Centos Stream 8 联网安装docker
    1.查看docker版本安装yum-config-manager#这个命令在yum-utils包yuminstall-yyum-utils下载docker-ce的源#下载docker-ce源文件yum-config-manager--add-repohttps:/......
  • Linux:RedHat8 设置中文输入法
    RadHat8自带中文输入法,只是默认没有使用。1.切换视图,搜索:Language快捷键:Win+Tab2.添加输入法3.切换输入法的快捷键super(Win)+空格 -----------------------------......
  • Linux磁盘分区
    在Linux的文件系统中,有个很重要的概念就是挂载,,除了根文件系统,其他所有文件系统都要先挂载到根文件系统中的某个目录之后才能访问。所谓的根文件系统就是系统启动的时候安......
  • linux 安装.net 5.0
    目录​​一、环境搭配​​​​二、下载SDK包​​​​ 三、ubuntu安装.net5.0​​ ​​四、创建.net5.0web项目​​ ​​五、发布web​​一、环境搭配首先在官网......