liunx之信号量与进程信号的基本介绍(1)

1.信号量是什么

情景:shm没有保护机制导致数据不一致的问题也可以通过信号量来解决

前置知识:

(1)多个进程进程看到的同一个公共资源也叫共享资源,被保护起来的共享资源叫做临界资源。

(2)数据不一致的前提:该共享资源未被保护且此时这个资源又能叫互斥资源而同时不同进程对应资源所处的代码段就叫临界区,与之相对的代码段叫非临界区。

(3)通过保护(管理)临界区的代码就可以变相保护临界资源。

(4)任何时刻下只允许一个执行流(进程)访问一个临界资源,叫做互斥而多个执行流访问同一个临界资源时具有一定的顺序性,叫同步。

(5)原子性的另一个意思是两态:要么做,要么不做。

2.锁的基本介绍

锁本身是一段代码,设计在临界区的前面,因此每个执行流在调用临界前都要去调用一下锁的,因此锁本身也是共享资源,为了防止锁上加锁的无穷递归,因此锁本身是原子性的,也就是锁允许一个执行流访问时其他的执行流都不允许用,通过锁的阻挡就只允许在一个时间点只有一个进程访问临界区了。

3.信号量的一个使用场景

信号量(sem)目前可以理解为计数器。

实际上我们可以将一块临界资源内部分成不同区域来使用,只要让不同进程访问不同位置就可以实现多进程的并发访问,此时信号量就可以作为计数器描述临界资源中资源数量的多少。所有进程想要访问临界资源中的一小块必须先申请信号量,这种操作的本质是对资源的预定操作。

可以说一个进程用信号量申请了一块资源,这块资源就允许该进程随时访问它且只允许该进程访问它(即使到最后该进程也没有访问它)。

信号量本身是一个struct,但我们目前先将其视为一个unsigned int类型的变量即可。

cpp 复制代码
struct semaphore
{
    raw_spinlock_t lock;
    unsigned int count;
    struct list_head wait_queue;
}

因此信号量本身也是共享资源,因此对conut进行--操作时也会由于锁而具有原子性,这种操作叫P操作,其申请++的操作叫V操作。所以信号量通过PV操作完成对资源的预定机制。

count值只有0或1的信号量叫二元信号量,此时叫做互斥的情况,其他count值的信号量叫多元信号量。

当资源是整体使用时就使用二元信号量,共享资源分区块使用时就是多元信号量。

wait_queue的用途:

count > 0,接着给后面的进程分配资源

count == 0,后面的进程没有资源分配了,于是就将后面的进程在这里阻塞挂起,直到count != 0就重新唤新进程并再次修改信号量。

信号量与通信之间的关系

(1)多进程使用同一个信号量,首先得保证每一个进程都能看到同一个信号量,system V的key机制就可以保证所有进程看到同一个信号量。

(2)不是传递数据才是进行通信(IPC)操作,而是两个进程在操作同一个共享资源这件事本身就算IPC了。

信号量中一些特有的接口

cpp 复制代码
int semget(key_t key,int nsems,int setflg);

返回值是一个semid,nsems此处是创建信号量的个数(也就是得到的其实是一个信号量的数组叫信号集)

setflg就是权限,和之前的通信方式一样

cpp 复制代码
int semctl(int semid,int semnum,int cmd,...);

这个函数可以说就是用于对semid对应的信号量进行初始化的。

cmd的标识符:

(1)SETVAL,使用他时,semnum代表该信号量数组的下标,此时...代表的是一个int val,代表semnum所要被初始化的值

(2)SETALL,semnum此时无效了,.此时..代表一个unisgned short *array,用于初始化semid中的所有信号量。

cpp 复制代码
int semop(int semid,struct sembuf*sops,size_t nops);

对semid执行PV操作的函数

cpp 复制代码
struct sembuf
{
    unsigned short sem_num;//信号量数组下标,从0开始
    short sem_op;//>0表示V操作,<0表示P操作
    short sem_flg;//默认设为0即可
}

因此sops就是sembuf的一个数组,nops就是说明数组的元素个数。整个函数就可以通过循环来统一操作数组中的元素。

OS中采用先描述再组织的方式管理信号集。

管理信号集的结构体叫struct semid_ds,其内部也有一个成员struct ipc_perm,因此信号量,通信队列和共享内存都是用key表示唯一性的。,所以这三者对于OS来说都被视为了同一种资源。

4.OS管理所有IPC资源的方式

解释:

(1)在OS中有一个全局的struct ipc_ids,其有一个成员entries指针,指向一个struct ipc_id_ary,其内部有一个柔性数组,存的是一个个kern_ipc_perm*类型的指针,能发现内部存的都是msg_queue,sem_array,shmid_kernel的第一个成员的地址,也就是其存储着这三种IPC的所有成员。

(2)其也间接的说明了shmid,msgid和semid的数值都是这个数组的下标(访问通信自身结构体的成员的方式就是找到kern_ipc_perm的地址然后进行对应类型的强转(如(msg_struct*)p[0])即可)。

(3)可以说这里的kern_ipc_perm就是基类,而三种IPC就是继承类,又实现了一个c语言的多态

(4)sem_array就是一个信号集,内部的一个成员管理着这个集的所有信号量

共享内存与进程之间的关系

shm其实同时被shmid_kernel和struct file管理着(shmid_kernel中有一个成员指向一个独立的struct file),所以可以说一个进程其实是通过struct file来间接找到shm的(因此shm有算是system V中比较特殊的一个了)。

5.进程信号的基本介绍

信号与信号量没有任何关系。

信号:给进程发送的用于进行事件异步运行的通信机制。

前提:

(1)即使进程没有接收到任何信号,进程也是提前知道所有信号如何处理的

(2)信号的处理不一定是立刻处理而是可以选择合适的时间等一会在处理

(3)进程是内置了对信号的识别和处理方式的

(4)给进程发送信号的信号源有很多

产生信号的方式(一部分)

(1)键盘产生信号

例:ctrl + c就是给目标进程发送信号的,很多信号的默认处理动作就是中止当前进程。

kill -l //查看信号表

bash 复制代码
ubuntu@VM-0-2-ubuntu:~$ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	

信号本质就是一个数字,旁边的是其的宏定义。

1~31号的信号是普通信号,没有32,33信号,34~64是实时信号,二者的区别就在于普通信号可以不立即处理而实时信号必须立即处理。

ctrl + c的本质就是给进程发送2号信号

处理信号的方式

(1)默认处理动作

(2)自定义处理动作

(3)忽略该信号

其中相当一部分信号的默认处理动作就是终止进程。

设置进程中一个信号的动作为自定义动作

bash 复制代码
typedef void(*sighander_t)(int);
sighander_t signal(int signum,sighander_t handler);

signum:一个普通信号的数字或宏定义。

handler:一个函数,能将进程在接收到signum对应的信号时进行的动作转换为调用handler函数。

因此说白了信号就是强制OS优先调用一个指定函数而已。

下面是信号的几个默认动作

bash 复制代码
       //终止进程
       Term   Default action is to terminate the process.
       //忽略信号
       Ign    Default action is to ignore the signal.
        //目前也视为中止进程
       Core   Default action is to terminate the process and dump core (see core(5)).
        //暂停进程
       Stop   Default action is to stop the process.
        //继续运行进程
       Cont   Default action is to continue the process if it is currently stopped.
相关推荐
2401_873479401 小时前
如何判断用户IP是否在商圈内?用IP地址查询定位实现LBS精准推送
linux·运维·服务器
平行云1 小时前
实时云渲染预启动技术解析:UE数字孪生应用的延迟优化机制(一)
linux·ue5·webgl·数字孪生·云渲染·实时云渲染·像素流
都在酒里1 小时前
Linux字符设备驱动开发(三):引入并发控制——使用mutex保护共享数据
linux·运维·驱动开发
慵懒的猫mi2 小时前
从 Windows 到 deepin:Electron 软件无损移植实战
linux·windows·deepin
坤昱2 小时前
cfs调度类深入解刨——最新内核细节分析1
linux·cfs·cfs调度·linux 7.1·eevdf·核心调度结构·linux最新调度分析
MC皮蛋侠客2 小时前
Perf 火焰图深度实战:CPU 性能分析与异常排查完全指南
linux·c++·性能分析·perf·火焰图
maosheng11462 小时前
NFS服务器的搭建有多种类型linux-linux
linux·运维·服务器
普通young man2 小时前
Linux基础开发工具集合
linux·运维·服务器
z200509302 小时前
【Linux学习】Linux中进程终止和进程等待
linux·学习·操作系统