nginx源码学习,linux体系结构,用户态,内核态,信号处理函数书写原则,错误范例

一、unix。linux体系结构

结构
内核 -> 系统调用 -> 公用库函数/shell -> 外部程序
类unix体系结构分为两个状态

  • (1)用户态
  • (2)内核态

操作系统/内核:用来控制计算机硬件资源,提供应用程序的运行环境

我们写的程序一般是在用户态,但是一些特殊代码的时候会切换到内核态

系统调通就是一些系统函数

shell:

bash(borne again shell重新装配的shell),它就是一种shell,linux默认采用的是bash着这种shell
通俗一点,bash是一个可执行程序,主要作用就是:命令解释
whereis bash
/usr/bin/bash
bash可以嵌套:
exit,exit,bash嵌套bash
在这里插入图片描述
shell的目的:
分割系统调用和应用程序

二、用户态和内核态之间的切换

内核态和用户态的不同:

  • 运行于用户态的进程可执行的操作和访问的资源会受到极大的限制
  • 内核态进程可进行任何操作,并且资源上没有限制

一个进程执行的时候,大部分时间都在用户态,但是有时候需要内核提供的服务
会切换到内核态,服务完成之后,再次切回来

为什么要这样划分,用户态,内核态

  • 1、避免危险操作
  • 2、系统调用的这些接口也是操作系统统一管理的
    资源是有限的,解决访问冲突,

什么时候从用户态切换到内核态?

  • 1、系统调通,比如malloc(sizeof(int))
  • 2、异常事件,信号
  • 3、外围设备中断

三、signal函数范例

可重入函数:在信号处理函数中,调用的时候,保证是安全的,异步调用安全
大家周知的函数都是不可重入的
如:malloc,printf
有些是可重用,异步安全函数,有些不是,自行百度
因为系统函数中由int error = num
但是如果你在信号处理中出错了,正常函数也出错了,那么这个error就不能正确显示错误了
信号处理函数原则:

  • 1、在信号处理中,尽量简单,尽量不要调用系统函数
  • 2、如果必须调用系统函数,那么一定调用可重入的,异步信号安全的系统函数
  • 3、如果一定要在信号处理中一定要调用会修改errno的值的函数,一定要备份,最终回复一下

signal不建议使用,知识在demo中使用一下

信号处理错误使用不可重用函数案例:

#include
#include
#include
#include

void sigHandler(int signo)
{
	void* p;
	//malloc是不可重用函数
	p = (void*)malloc(1);
	free(p);

	if (signo == SIGUSR1)
	{
		printf("捕捉到了SIGUSR1信号\n");
	}
	else if (signo == SIGUSR2)
	{
		printf("捕捉到了SIGUSR2信号\n");
	}
	else
	{
		printf("收到了未捕捉的信号d%\n", signo);
	}
}

int main()
{
	printf("process start");

	if (signal(SIGUSR1, sigHandler) == SIG_ERR)
	{
		printf("无法捕捉SIGUSR1信号");
	}
	if (signal(SIGUSR2, sigHandler) == SIG_ERR)
	{
		printf("无法捕捉SIGUSR2信号");
	}

	for (; ;)
	{
		void* p;
		p = (int*)malloc(sizeof(1));
		free(p);
	}

}

bash1中进行编译,启动
nginx源码学习,linux体系结构,用户态,内核态,信号处理函数书写原则,错误范例_第1张图片
bash2中查看运行状态,并给进程一个LinuxTestCSave信号
R+表示前台运行
nginx源码学习,linux体系结构,用户态,内核态,信号处理函数书写原则,错误范例_第2张图片
nginx源码学习,linux体系结构,用户态,内核态,信号处理函数书写原则,错误范例_第3张图片

查看运行状态
S+表示已经休眠了,程序已经出错了
nginx源码学习,linux体系结构,用户态,内核态,信号处理函数书写原则,错误范例_第4张图片

你可能感兴趣的