Linux之信号量,比较全面,个人总结。
Linux信号量

Linux信号量信号在Linux中是⼀个⽐较常见的概念,例如我们按Ctrl+C中断前台进程,通过Kill命令结束进程都是通过信号实现的。
下⾯就以Ctrl+C为例简单的说明信号的处理流程:⽤户按下Ctrl-C,这个键盘输⼊产⽣⼀个硬件中断。
该进程的⽤户空间代码暂停执⾏,CPU从⽤户态切换到内核态处理硬件中断。
终端驱动程序将Ctrl-C解释成⼀个SIGINT信号,记在该进程的PCB中(也可以说发送了⼀个SIGINT信号给该进程)。
当内核返回到该进程的⽤户空间代码继续执⾏之前,⾸先处理PCB中记录的信号,发现有⼀个SIGINT信号待处理,⽽这个信号的默认处理动作是终⽌进程,所以直接终⽌进程⽽不再返回它的⽤户空间代码执⾏。
kill -l 命令可看到Linux⽀持的信号列表:1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR111) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+338) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+843) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+1348) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-1253) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-758) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-263) SIGRTMAX-1 64) SIGRTMAX列表中,编号为1 ~ 31的信号为传统UNIX⽀持的信号,是不可靠信号(⾮实时的),编号为32 ~ 63的信号是后来扩充的,称做可靠信号(实时信号)。
Linux高级调试与优化——信号量机制与应用程序崩溃

Linux⾼级调试与优化——信号量机制与应⽤程序崩溃背景介绍 Linux分为内核态和⽤户态,⽤户态通过进⼊内核态执⾏。
⽤户空间的glibc库将Linux内核系统调⽤封装成GNU C Library库⽂件(兼容ANSI & POSIX C语⾔标准),同时提供了其他特性的⽀持。
应⽤程序通常不是直接调⽤Linux内核的系统调⽤接⼝,⽽是通过glibc库封装的接⼝间接调⽤Linux内核系统调⽤。
信号量机制 关于Linux信号量机制的原理,建议阅读《Unix环境⾼级编程》第10章,本博客只是简单介绍其原理。
信号量是⼀种软中断,⽤来实现Linux内核和应⽤程序之间的异步通信。
每⼀个信号量由⼀个4字节整形数据表⽰。
可以通过man 7 signal查看所有信号量描述。
其中1~32号信号量是从Unix继承⽽来,33~64是Linux内核定义的信号量。
Linux内核为每个信号量设置了默认处理动作,如Term(终⽌执⾏)、Ign(忽略)、Core(终⽌执⾏并产⽣coredump)、Stop(停⽌运⾏)和Cont(继续运⾏),当应⽤程序接收到某个信号量时,则按照默认处理动作执⾏。
应⽤程序也可以通过sigaction()或者signal()函数修改默认的处理动作,⽐如屏蔽或者忽略某个信号量等。
应⽤程序信号量处理函数通常是链接glibc中默认的信号量处理函数,也可以⾃⼰编写和指定信号量处理函数。
但是需要注意的是,SIGKILL和SIGSTOP信号量不能被捕获(caught)、屏蔽(blocked)或者忽略(ignored)。
信号量触发情况有三种: 1)Linux内核检测到应⽤程序异常,发送特定的信号量给应⽤程序,应⽤程序捕获到信号量后,调⽤信号量处理函数; 2)Linux内核因为内部事件⽽给应⽤程序发送特定信号,通知应⽤程序发⽣了某个事件,如著名的segmentation fault,应⽤程序捕获到信号量后,调⽤信号量处理函数; 3)Linux内核检测到外部事件,如Ctrl+C,Ctrl+Z等,发送特定信号给应⽤程序,应⽤程序捕获到信号量后,调⽤信号量处理函数;Signal Value Action CommentSIGHUP1Term Hangup detected on controlling terminal or death of controlling processSIGINT2Term Interrupt from keyboardSIGQUIT3Core Quit from keyboardSIGILL4Core Illegal InstructionSIGTRAP5Core Trace/breakpoint trapSIGABRT6Core Abort signal from abort(3)SIGIOT6Core IOT trap. A synonym for SIGABRTSIGEMT7TermSIGFPE8Core Floating point exceptionSIGKILL9Term Kill signal, cannot be caught, blocked or ignored.SIGBUS10,7,10Core Bus error (bad memory access)SIGSEGV11Core Invalid memory referenceSIGPIPE13Term Broken pipe: write to pipe with no readersSIGALRM14Term Timer signal from alarm(2)SIGTERM15Term Termination signalSIGUSR130,10,16Term User-defined signal 1SIGUSR231,12,17Term User-defined signal 2SIGCHLD20,17,18Ign Child stopped or terminatedSIGCONT19,18,25Cont Continue if stoppedSIGSTOP17,19,23Stop Stop process, cannot be caught, blocked or ignored.SIGTSTP18,20,24Stop Stop typed at terminalSIGTTIN21,21,26Stop Terminal input for background processSIGTTOU22,22,27Stop Terminal output for background processSIGIO23,29,22Term I/O now possible (4.2BSD)SIGPOLL Term Pollable event (Sys V). Synonym for SIGIOSIGPROF27,27,29Term Profiling timer expiredSIGSYS12,31,12Core Bad argument to routine (SVr4)SIGURG16,23,21Ign Urgent condition on socket (4.2BSD)SIGVTALRM 26,26,28Term Virtual alarm clock (4.2BSD)SIGVTALRM 26,26,28Term Virtual alarm clock (4.2BSD)SIGXCPU24,24,30Core CPU time limit exceeded (4.2BSD)SIGXFSZ25,25,31Core File size limit exceeded (4.2BSD)SIGSTKFLT16Term Stack fault on coprocessor (unused)SIGCLD18Ign A synonym for SIGCHLDSIGPWR29,30,19Term Power failure (System V)SIGINFO29 A synonym for SIGPWR, on an alphaSIGLOST29Term File lock lost (unused), on a sparcSIGWINCH28,28,20Ign Window resize signal (4.3BSD, Sun)SIGUNUSED31Core Synonymous with SIGSYS信号量进阶 关于⾃定义信号量处理函数、屏蔽指定信号量等操作,参考 信号量处理函数实质上是应⽤程序发⽣异常时的⼀种修复或者调试机制,因为信号量处理不是正常的函数调⽤,因此它会复⽤⽗函数的栈,如果信号量处理函数中发⽣了异常,系统是没有办法处理的,因此,信号量处理函数必须是安全可靠的。
Linux之信号量,比较全面,个人总结。

信号量一.什么是信号量信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。
信号量的值为正的时候,说明它空闲。
所测试的线程可以锁定而使用它。
若为0,说明它被占用,测试的线程要进入睡眠队列中,等待被唤醒。
二.信号量的分类在学习信号量之前,我们必须先知道——Linux提供两种信号量:POSIX信号量又分为有名信号量和无名信号量。
有名信号量,其值保存在文件中, 所以它可以用于线程也可以用于进程间的同步。
无名信号量,其值保存在内存中。
倘若对信号量没有以上的全面认识的话,你就会很快发现自己在信号量的森林里迷失了方向。
三.内核信号量1.内核信号量的构成内核信号量类似于自旋锁,因为当锁关闭着时,它不允许内核控制路径继续进行。
然而,当内核控制路径试图获取内核信号量锁保护的忙资源时,相应的进程就被挂起。
只有在资源被释放时,进程才再次变为可运行。
只有可以睡眠的函数才能获取内核信号量;中断处理程序和可延迟函数都不能使用内核信号量。
count:相当于信号量的值,大于0,资源空闲;等于0,资源忙,但没有进程等待这个保护的资源;小于0,资源不可用,并至少有一个进程等待资源。
wait:存放等待队列链表的地址,当前等待资源的所有睡眠进程都会放在这个链表中。
sleepers:存放一个标志,表示是否有一些进程在信号量上睡眠。
2.内核信号量中的等待队列(删除,没有联系)上面已经提到了内核信号量使用了等待队列wait_queue来实现阻塞操作。
当某任务由于没有某种条件没有得到满足时,它就被挂到等待队列中睡眠。
当条件得到满足时,该任务就被移出等待队列,此时并不意味着该任务就被马上执行,因为它又被移进工作队列中等待CPU资源,在适当的时机被调度。
内核信号量是在内部使用等待队列的,也就是说该等待队列对用户是隐藏的,无须用户干涉。
由用户真正使用的等待队列我们将在另外的篇章进行详解。
3.内核信号量的相关函数(2)申请内核信号量所保护的资源:4.内核信号量的使用例程在驱动程序中,当多个线程同时访问相同的资源时(驱动中的全局变量时一种典型的共享资源),可能会引发“竞态“,因此我们必须对共享资源进行并发控制。
Linux 信号量、共享内存和消息队列

4
SV IPC 系统调用
功能 消息队列 信号量 共享内存
分配一个IPC对象,获 msgget 对象, 分配一个 对象 得对IPC的访问 得对 的访问
semget
shmget
IPC操作 发送 接收 msgsnd/ semop 操作: 发送/接收 操作 消息,信号量操作, 消息,信号量操作,连 msgrcv 接/释放共享内存 释放共享内存 IPC控制:获得/修改 msgctl 控制:获得 修改 控制 状态信息,取消IPC 状态信息,取消 semctl
3
struct ipc_perm
struct ipc_perm { u i d _ t u i d ; /* owner's effective user id */ g i d _ t g i d ; /* owner's effective group id */ u i d _ t cuid; /* creator's effective user id */ g i d _ t c g i d ; /* creator's effective group id */ m o d e _ t mode; /* access modes */ u l o n g s e q ; /* slot usage sequence number */ k e y _ t key; /* key */ }
10
信号量系统调用
#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget(key_t key, int nsems, int semflg); int semop(int semid, struct sembuf *sops, unsigned nsops); int semctl(int semid, int semnum, int cmd, ...);
Linux编程之信号量

Linux编程之信号量信号量分 System V 信号量和 POSIX 信号量,这⾥仅介绍 POSIX 信号量。
1. 概述2. 命令信号量3. 信号量操作3.1 等待⼀个信号量sem_wait() 函数会递减(减⼩ 1)sem 引⽤的信号量的值。
#include <semaphore.h>int sem_wait(sem_t *sem);如果信号量的当前值⼤于 0,那么 sem_wait() 会⽴即返回。
如果信号量的当前值等于 0,那么 sem_wait() 会阻塞直到信号量的值⼤于 0 为⽌,当信号量值⼤于 0 时该信号量值就被递减并且sem_wait() 会返回。
如果⼀个阻塞的 sem_wait() 调⽤被⼀个信号处理器中断了,那么它就会失败并返回 EINTR 错误,不管在使⽤ sigaction() 建⽴这个信号处理器时是否采⽤了 SA_RESTART 标记。
(在其他⼀些 UNIX 实现上,SA_RESTART 会导致 sem_wait() ⾃动重启。
)3.1.1 sem_trywait()sem_trywait() 函数是 sem_wait() 的⼀个⾮阻塞版本。
#include <semaphore.h>int sem_trywait(sem_t *sem);如果递减操作⽆法⽴即被执⾏,那么 sem_trywait() 就会失败并返回 EAGAIN 错误。
3.1.2 sem_timedwait()sem_timedwait() 函数是 sem_wait() 的另⼀个变体,它允许调⽤者为调⽤被阻塞的时间量指定⼀个限制。
#define _XOPEN_SOURCE 600#include <semaphore.h>int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);如果 sem_timedwait() 调⽤因超时⽽⽆法递减信号量,那么这个调⽤就会失败并返回 ETIMEDOUT 错误。
Linux内核信号量分析

问题作具体剖析 。
二 、Linux 内核信号量操作代码分析
在 Linux - 216110 内核中 , 内核信号量的数据 结构类型是在 includeΠasm - i386 Πsemaphore1h 中定 义的 :
struct semaphore { atomic - t count ; int sleepers ; wait - queue - head - t wait ; }; 其中的成员 wait 就是等待进入临界区的进程链 表头 。可以通过下面的方式静态地声明一个信号量 (计数信号量或互斥信号量) : static - DECLARE- SEMAPHORE- GENERIC (name ,count) ; 其中 name 是信号量变量名 ,而 count 是使用者数 量 ,当 count 值大于 1 时 ,该信号量就是计数信号量。 创建互斥信号量还可以使用下面地快捷方式之一 : static DECLARE- MUTEX ( name) ;Π3 name1count 初值为 1 3 Π static DECLARE- MUTEX- LOCKED ( name ) ;Π3 name1count 初值为 0 3 Π
收稿日期 : 2008 - 07 - 15 作者简介 : 王亚军 (1978 - ) , 男 , 黑龙江绥化市人 , 中国人民武装警察部队学院计算机教研室讲师 , 研究方向为嵌 入式 Linux 系统设计 。
100
2008 年第 3 期 (总第 12 期)
王亚军 : Linux 内核信号量分析
两者用途不同 ,但都是通过前面的宏定义- DECLARE- SEMAPHORE- GENERIC ( ) 来实现的 。对 信号量的 down () 和 up () 等操作函数也是在同一文 件中定义的 ,函数头如下 :
linux信号量机制

linux信号量机制(semaphore)信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。
当公共资源增加时,调用函数sem_post()增加信号量。
只有当信号量值大于0时,才能使用公共资源,使用后,函数sem_wait()减少信号量。
函数sem_trywait()和函数pthread_ mutex_trylock()起同样的作用,它是函数sem_wait()的非阻塞版本。
它们都在头文件/usr/include/semaphore.h中定义。
信号量的数据类型为结构sem_t,它本质上是一个长整型的数。
函数sem_init()用来初始化一个信号量。
它的原型为:extern int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));sem为指向信号量结构的一个指针;pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value给出了信号量的初始值。
函数sem_post( sem_t *sem )用来增加信号量的值。
当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。
函数sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。
函数sem_trywait ( sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。
函数sem_destroy(sem_t *sem)用来释放信号量sem。
例1:使用信号量。
例子中一共有4个线程,其中两个线程负责从文件读取数据到公共的缓冲区,另两个线程从缓冲区读取数据作不同的处理(加和乘运算)。
/* File sem.c */#include <stdio.h>#include <pthread.h>#include <semaphore.h>#define MAXSTACK 100int stack[MAXSTACK][2];int size=0;sem_t sem;/* 从文件1.dat读取数据,每读一次,信号量加一*/void ReadData1(void){FILE *fp=fopen("1.dat","r");while(!feof(fp)){fscanf(fp,"%d %d",&stack[size][0],&stack[size][1]);sem_post(&sem);++size;}fclose(fp);}/*从文件2.dat读取数据*/void ReadData2(void){FILE *fp=fopen("2.dat","r");while(!feof(fp)){fscanf(fp,"%d %d",&stack[size][0],&stack[size][1]);sem_post(&sem);++size;}fclose(fp);}/*阻塞等待缓冲区有数据,读取数据后,释放空间,继续等待*/ void HandleData1(void){while(1){sem_wait(&sem);printf("Plus:%d+%d=%d\n",stack[size][0],stack[size][1],stack[size][0]+stack[size][1]);--size;}}void HandleData2(void){while(1){sem_wait(&sem);printf("Multiply:%d*%d=%d\n",stack[size][0],stack[size][1],stack[size][0]*stack[size][1]);--size;}}int main(void){pthread_t t1,t2,t3,t4;sem_init(&sem,0,0);pthread_create(&t1,NULL,(void *)HandleData1,NULL);pthread_create(&t2,NULL,(void *)HandleData2,NULL);pthread_create(&t3,NULL,(void *)ReadData1,NULL);pthread_create(&t4,NULL,(void *)ReadData2,NULL);/* 防止程序过早退出,让它在此无限期等待*/pthread_join(t1,NULL);}在Linux下,用命令gcc -lpthread sem.c -o sem生成可执行文件sem。
Linux信号量机制

大作业---Linux信号量机制姓名:学号:班级:010914日期:2012年5月23日进程A、B、C,分别调用过程get、copy、put对缓冲区S和T进行操作。
其中get负责从文件F_in中把数据块读入并输出缓冲区S,copy负责从S中提取数据块并复制到缓冲区T中,put负责从缓冲区T中取出信息存入到本地文件F_out中。
实现get、copy、put的操作过程。
get copy put缓冲区S 缓冲区T功能需求:● 提供与用户交互的界面,用户可指定输入、输出文件以及缓冲区大小● 利用信号量实现互斥● 同时产生多个get、copy和put线程,利用信号量实现多个相同功能的线程间的通信,避免临界资源的非法访问,可参考读写者问题解决方案● 支持文件输入、输出非功能需求:● 程序应有较好的容错性(即能对用户输入的命令进行判断,并对错误的命令进行错误处理)过程需求:● 使用vi进行代码的编写● 使用make工具建立工程● 将实现不同类别功能的函数写到不同的.c文件中,并使用makefile链接编译。
2.1 结构设计进程1通过get函数将源文件载入缓冲区S;进程2通过copy函数将数据从缓冲区S复制到缓冲区T内;进程3通过put函数将缓冲区T内的数据输出到目标文件。
2.2 功能设计1.提供与用户交互的界面,用户可指定输入、输出文件以及缓冲区大小。
2.利用信号量实现互斥。
3.同时产生多个get、copy和put线程,利用信号量实现多个相同功能的线程间的通信,避免临界资源的非法访问。
3 测试和使用说明3.1 使用说明1、执行make命令,编译程序test;2、执行test;3、输入源文件的路径4、输入目标文件的文件名5、输入缓冲区大小6、程序执行完毕3.2 测试说明执行make命令,编译test。
输入文件fin内容如上图。
./fin运行可执行程序test,程序请求用户指定输入文件、输出文件和缓冲区大小。
程序获取用户输入后,根据设计要求将输入文件的内容复制到输出文件中,并显示执行过程和执行状态。
【IT专家】进程间通信方式总结——信号量

进程间通信方式总结——信号量2017/04/14 0 Linux/Unix系统IPC是各种进程间通信方式的统称,但是其中极少能在所有Linux/Unix系统实现中进行移植。
随着POSIX和Open Group (X/Open)标准化的推进呵护影响的扩大,情况虽已得到改善,但差别仍然存在。
一般来说,Linux/Unix常见的进程间通信方式有:管道、消息队列、信号、信号量、共享内存、套接字等。
博主将在《进程间通信方式总结》系列博文中和大家一起探讨学习进程间通信的方式,并对其进行总结,让我们共同度过这段学习的美好时光。
这里我们就以其中一种方式信号量展开探讨,为了防止出现因多个程序同时访问同一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域。
临界区域是指执行数据更新的代码需要独占式地执行。
而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问它,也就是说信号量是用来调协进程对共享资源的访问的。
由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的: P(sv):如果sv的大于零,就给它减1;如果它的为零,就挂起该进程的执行 V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1。
Linux提供了一组精心设计的信号量接口来对信号进行操作,它们不只是针对二进制信号量,下面将会对这些函数进行介绍,但请注意,这些函数都是用来对成组的信号量进行操作的。
它们声明在头文件sys/sem.h中。
下面让我们一起来看看信号量的操作函数吧! 函数介绍semget函数原型:intsemget(key_tkey,intnum_sems,intsem_flags); key:当key 为0(IPC_PRIVATE),会建立新信号量集对象;当为大于0的32位整数,视参数flags来确定操作。
Linux信号量线程控制--培训教程

信号量线程控制(1)信号量说明在第8 章中已经讲到,信号量也就是操作系统中所用到的PV 原语,它广泛用于进程或线程间的同步与互斥。
信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。
这里先来简单复习一下PV原语的工作原理。
PV原语是对整数计数器信号量sem的操作。
一次P操作使sem减一,而一次V操作使《嵌入式Linux应用程序开发详解》——第9章、多线程编程sem 加一。
进程(或线程)根据信号量的值来判断是否对公共资源具有访问权限。
当信号量sem 的值大于等于零时,该进程(或线程)具有公共资源的访问权限;相反,当信号量sem 的值小于零时,该进程(或线程)就将阻塞直到信号量sem的值大于等于0 为止。
PV 原语主要用于进程或线程间的同步和互斥这两种典型情况。
若用于互斥,几个进程(或线程)往往只设置一个信号量sem,它们的操作流程如图9.2 所示。
当信号量用于同步操作时,往往会设置多个信号量,并安排不同的初始值来实现它们之间的顺序执行,它们的操作流程如图9.3所示。
图9.2 信号量互斥操作华清远见<嵌入式Linux应用开发班>培____________训教材图9.3 信号量同步操作(2)函数说明Linux 实现了POSIX 的无名信号量,主要用于线程间的互斥同步。
这里主要介绍几个常见函数。
• sem_init用于创建一个信号量,并能初始化它的值。
• sem_wait和sem_trywait相当于P操作,它们都能将信号量的值减一,两者的区别在于若信号量小于零时,sem_wait将会阻塞进程,而sem_trywait则会立即返回。
• sem_post相当于V操作,它将信号量的值加一同时发出信号唤醒等待的进程。
• sem_getvalue用于得到信号量的值。
• sem_destroy用于删除信号量。
(3)函数格式表9.11 列出了sem_init函数的语法要点。
表9.11 sem_init函数语法要点所需头文件#include <semaphore.h>《嵌入式Linux应用程序开发详解》——第9章、多线程编程函数原型int sem_init(sem_t *sem,int pshared,unsigned int value)sem:信号量pshared:决定信号量能否在几个进程间共享。
Linux信号量大全

Linux信号量⼤全Linux 信号量⼤全⼀、内核如何实现信号的捕捉如果信号的处理动作是⽤户⾃定义函数,在信号递达时就调⽤这个函数,这称为捕捉信号。
由于信号处理函数的代码是在⽤户空间的,处理过程⽐较复杂,举例如下:1. ⽤户程序注册了SIGQUIT信号的处理函数sighandler。
2. 当前正在执⾏main函数,这时发⽣中断或异常切换到内核态。
3. 在中断处理完毕后要返回⽤户态的main函数之前检查到有信号SIGQUIT递达。
4. 内核决定返回⽤户态后不是恢复main函数的上下⽂继续执⾏,⽽是执⾏sighandler函数,sighandler和main函数使⽤不同的堆栈空间,它们之间不存在调⽤和被调⽤的关系,是两个独⽴的控制流程。
(By default, the signal handler is invoked on the normal process stack. It is possible to arrange that the signal handler uses an alternate stack; see sigaltstack(2) for a discussion of how to do this and when it might be useful.)5. sighandler函数返回后⾃动执⾏特殊的系统调⽤sigreturn再次进⼊内核态。
6. 如果没有新的信号要递达,这次再返回⽤户态就是恢复main函数的上下⽂继续执⾏了。
上图出⾃ULK⼆、sigaction函数#include <signal.h>int sigaction(int signo,const srtuct sigaction *act,struct sigaction *oact);sigaction函数可以读取和修改与指定信号相关联的处理动作。
调⽤成功则返回0,出错则返回-1。
Signo是指定要操作信号的编号。
linux下信号量通信实现的心得1000字

linux下信号量通信实现的心得1000字摘要:一、引言1.介绍Linux下信号量通信的背景和意义2.总结文章结构二、信号量基础知识1.信号量的定义和作用2.Linux下信号量的实现机制3.信号量的基本操作三、信号量通信的实现方法1.互斥锁和条件变量的使用2.进程间通信的实例3.信号量通信的优缺点四、实际应用中的注意事项1.信号量初始化的时机和方法2.避免死锁的处理方法3.信号处理与信号量通信的结合五、总结与展望1.总结信号量通信在Linux下的实现心得2.展望信号量通信的发展趋势和应用领域正文:一、引言在Linux操作系统中,信号量通信是一种非常重要的进程间通信方式。
信号量机制可以有效地解决多进程或多线程在共享资源访问时的同步问题,避免竞争条件和资源冲突。
本文将结合个人在实际项目中的经验,对Linux下信号量通信的实现心得进行总结,以期为大家提供一定的借鉴和启示。
本文将分为五个部分进行论述,分别为:信号量基础知识、信号量通信的实现方法、实际应用中的注意事项、总结与展望。
二、信号量基础知识1.信号量的定义和作用信号量是一种用于控制进程或线程之间对共享资源访问的同步机制。
它的主要作用是实现对共享资源的互斥访问和顺序访问。
信号量有两个主要属性:计数器和权限位。
计数器用于表示共享资源的剩余数量,权限位用于表示各个进程或线程对资源的访问权限。
2.Linux下信号量的实现机制在Linux操作系统中,信号量是通过一组整数变量来实现的。
这组变量包括信号量的值、信号量的状态、信号量的拥有者等。
信号量的操作主要包括:初始化、P操作(尝试获取资源)、V操作(释放资源)等。
3.信号量的基本操作(1)初始化:通过sem_init()函数对信号量进行初始化,设置信号量的值和状态。
(2)P操作:通过sem_wait()函数尝试获取信号量资源。
若信号量值为0,表示资源已被占用,P操作将阻塞进程,直到信号量值变为1。
(3)V操作:通过sem_post()函数释放信号量资源,将信号量值加1。
Linux互斥锁、条件变量和信号量

Linux--Linux互斥锁、条件变量和信号量进行多线程编程,最应该注意的就是那些共享的数据,因为无法知道哪个线程会在哪个时候对它进行操作,也无法得知哪个线程会先运行,哪个线程会后运行。
所以,要对这些资源进行合理的分配和正确的使用。
在Linux下,提供了互斥锁、条件变量和信号量来对共享资源进行保护。
一、互斥锁互斥锁,是一种信号量,常用来防止两个进程或线程在同一时刻访问相同的共享资源。
需要的头文件:pthread.h互斥锁标识符:pthread_mutex_t(1)互斥锁初始化:函数原型:int pthread_mutex_init (pthread_mutex_t* mutex,const pthread_mutexattr_t* mutexattr);函数传入值:mutex:互斥锁。
mutexattr:PTHREAD_MUTEX_INITIALIZER 创建快速互斥锁。
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP 创建递归互斥锁。
PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP 创建检错互斥锁。
函数返回值:成功:0;出错:-1(2)互斥操作函数int pthread_mutex_lock(pthread_mutex_t* mutex); //上锁int pthread_mutex_trylock (pthread_mutex_t* mutex); //只有在互斥被锁住的情况下才阻塞int pthread_mutex_unlock (pthread_mutex_t* mutex); //解锁int pthread_mutex_destroy (pthread_mutex_t* mutex); //清除互斥锁函数传入值:mutex:互斥锁。
函数返回值:成功:0;出错:-1使用形式:pthread_mutex_t mutex;pthread_mutex_init (&mutex, NULL); /*定义*/...pthread_mutex_lock(&mutex); /*获取互斥锁*/... /*临界资源*/pthread_mutex_unlock(&mutex); /*释放互斥锁*/备注:互斥锁MUTEX的使用注意lock和unlock的配对使用,否则容易出现死锁发生。
linux 任务间通信 共享内存 信号量 例程

linux 任务间通信共享内存信号量例程Linux任务间通信主要有以下几种方式:管道(pipe)、命名管道(named pipe)、信号量(semaphore)、消息队列(message queue)、共享内存(shared memory)等。
下面我将分别介绍这些通信方式的例程。
1. 管道(pipe):管道是一种半双工的通信方式,数据只能单向流动,且只能在具有亲缘关系的进程间使用。
管道分为匿名管道和命名管道两种。
匿名管道示例:c#include <stdio.h>#include <unistd.h>int main() {int pipefd[2];pid_t cpid;char buf;if (pipe(pipefd) == -1) {perror("pipe");exit(EXIT_FAILURE);}cpid = fork();if (cpid == -1) {perror("fork");exit(EXIT_FAILURE);}if (cpid == 0) { // 子进程close(pipefd[0]); // 关闭读端write(pipefd[1], "hello", 5); // 向管道中写入数据close(pipefd[1]); // 关闭写端exit(EXIT_SUCCESS);} else { // 父进程close(pipefd[1]); // 关闭写端read(pipefd[0], &buf, 1); // 从管道中读取数据printf("parent: %c", buf);close(pipefd[0]); // 关闭读端}return 0;}2. 命名管道(named pipe):命名管道是一种全双工的通信方式,可以在任意两个进程之间使用。
命名管道的主要优点是可以实现无亲缘关系进程间的通信。
【linux】信号量的值定义

【linux】信号量的值定义from/joeblackzqq/article/details/438165092 015.02参见文件:/usr/include/bits/signum.h[cpp] view plain copy /* Signal number definitions. Linux version. Copyright (C) 1995-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see</licenses/>. */ #ifdef_SIGNAL_H /* Fake signal functions. */ #define SIG_ERR ((__sighandler_t) -1) /* Error return. */ #define SIG_DFL ((__sighandler_t) 0) /* Default action. */ #define SIG_IGN ((__sighandler_t) 1)/* Ignore signal. */ #ifdef __USE_UNIX98 # define SIG_HOLD ((__sighandler_t) 2) /* Add signal to hold mask. */ #endif /* Signals. */ #define SIGHUP 1 /* Hangup (POSIX). */ #define SIGINT 2/* Interrupt (ANSI). */ #define SIGQUIT 3 /* Quit (POSIX). */ #define SIGILL 4 /* Illegal instruction (ANSI). */ #define SIGTRAP 5 /* Trace trap (POSIX). */ #define SIGABRT 6 /* Abort (ANSI). */ #define SIGIOT 6 /* IOT trap (4.2 BSD). */ #define SIGBUS 7 /* BUS error (4.2 BSD). */ #define SIGFPE 8 /*Floating-point exception (ANSI). */ #define SIGKILL9 /* Kill, unblockable (POSIX). */ #define SIGUSR110 /* User-defined signal 1 (POSIX). */ #define SIGSEGV 11 /* Segmentation violation (ANSI). */ #define SIGUSR2 12 /* User-defined signal 2 (POSIX). */ #define SIGPIPE 13 /* Broken pipe (POSIX). */ #define SIGALRM 14 /* Alarm clock(POSIX). */ #define SIGTERM 15 /* Termination (ANSI). */ #define SIGSTKFLT 16 /* Stack fault.*/ #define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ #define SIGCHLD 17 /* Child status has changed (POSIX). */ #define SIGCONT 18 /* Continue (POSIX). */ #define SIGSTOP 19 /* Stop, unblockable (POSIX). */#define SIGTSTP 20 /* Keyboard stop (POSIX). */ #define SIGTTIN 21 /* Background read from tty (POSIX). */ #define SIGTTOU 22 /* Background write to tty (POSIX). */ #define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */ #define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */ #define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */ #define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */ #define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */ #define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */ #define SIGPOLL SIGIO /* Pollable event occurred (System V). */ #define SIGIO 29 /* I/O now possible (4.2 BSD). */ #define SIGPWR 30 /* Power failure restart (System V). */ #define SIGSYS31 /* Bad system call. */ #define SIGUNUSED 31 #define _NSIG 65 /* Biggest signal number + 1 (including real-time signals). */ #define SIGRTMIN (__libc_current_sigrtmin ()) #define SIGRTMAX(__libc_current_sigrtmax ()) /* These are the hard limits of the kernel. These values should not be used directly at user level. */ #define __SIGRTMIN 32#define __SIGRTMAX (_NSIG - 1) #endif /*<signal.h> included. */。
操作系统综合题知识点笔记

操作系统综合题知识点笔记可能会算特别大的数字,请带上计算器。
1. 信号量(semaphore)对一个信号量有2种操作:down&up(或者用P&V来表示)。
down操作检查信号量S是否大于0,是则将S减1并继续,否则使进程睡眠。
up操作检查有无进程在S上睡眠,是则唤醒其中一个进程,否则将S加1。
注意,旧版down操作无论S是否大于0都将S减1;旧版up操作无论有无进程在睡眠都将S加1。
即down操作检查信号量S是否大于0,是则将S减1然后继续,否则将S减1然后使进程睡眠。
up操作检查有无进程在S上睡眠,是则将S加1然后唤醒其中一个进程,否则将S加1。
题目默认隐含的假设:所有进程都在开始时就启动了。
不能在中途启动进程。
光看这个没什么用,做做课后题或往年试题。
2.调度(scheduling)周转时间(turnaround time):一个批处理作业从提交到完成的统计平均时间。
忽略进程切换(process switch,又称上下文切换context switch)的时间,一个进程从提交到完成的时间等于等待时间与运行时间之和。
原因:一个进程从提交到完成要么在等待,要么在运行。
(答题时最好抄一下原因,证明一下再用)答题时请列出进程运行的时间轴(推荐用甘特图(Gantt chart)代替,比较繁琐但是思路清晰)。
A.先来先服务(First-Come First-Served, FCFS):顾名思义。
有护航效果(Convoy Effect)。
B.最短作业优先(Shortest Job First, SJF):顾名思义。
C.最短剩余时间优先(Shortest Remaining Time Next):顾名思义。
与最短作业优先的区别:假如一个长作业(进程)正在运行时,有一个短作业(进程)到达,SJF不会将正在运行的长作业中断然后让短作业先运行,而最短剩余时间优先会。
D.转轮调度(Round Robin):先设定时间片(quantum)的值,让进程按照先来后到排队,将队首的进程运行一个时间片后,把它放到队尾,然后运行下一个在队首的进程。
linux semaphore 用法

linux semaphore 用法下列关于Linux 信号量(Semaphore)的用法的文章将逐步回答这一问题。
信号量是一种用于进程同步和互斥操作的工具,在多进程编程中扮演了重要的角色。
本文将覆盖信号量的概念、使用方法以及一些示例场景。
1. 了解信号量的概念信号量是一种计数器,用于控制多个进程对共享资源的访问。
它可以允许多个进程同时访问资源,也可以限制只能有一个进程访问资源。
信号量有两个主要操作:P(等待)和V(释放)。
P 操作减少信号量的值,如果结果小于零,则阻塞进程。
V 操作增加信号量的值,如果有进程正在等待,那么唤醒一个正在等待的进程。
2. 安装和初始化信号量在Linux 中,可以使用System V 信号量(sys/sem.h)或POSIX 信号量(semaphore.h)。
我们首选POSIX 信号量,因为它更易使用,并且在大多数现代Linux 发行版中都得到了广泛支持。
要使用POSIX 信号量,首先需要包含适当的头文件,并初始化信号量。
#include <semaphore.h>int main() {sem_t semaphore;sem_init(&semaphore, 0, 1);...return 0;}在上面的示例中,我们创建了一个名为"semaphore" 的信号量,并使用sem_init 函数对其进行初始化。
第二个参数是标志,通常为0。
第三个参数是信号量的初始值。
3. 使用信号量进行进程同步信号量可用于实现互斥或同步操作。
在互斥模式中,信号量的初始值通常设置为1,以确保只有一个进程可以访问临界区。
在同步模式中,信号量的初始值通常设置为0,以确保一个进程等待另一个进程完成某个操作。
互斥模式示例:#include <semaphore.h>sem_t semaphore;void critical_section() {sem_wait(&semaphore); P 操作临界区代码sem_post(&semaphore); V 操作}int main() {sem_init(&semaphore, 0, 1);创建多个进程执行critical_section...return 0;}在上面的示例中,我们使用sem_wait 和sem_post 函数分别实现了P 和V 操作。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
信号量一.什么是信号量信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。
信号量的值为正的时候,说明它空闲。
所测试的线程可以锁定而使用它。
若为0,说明它被占用,测试的线程要进入睡眠队列中,等待被唤醒。
二.信号量的分类在学习信号量之前,我们必须先知道——Linux提供两种信号量:POSIX信号量又分为有名信号量和无名信号量。
有名信号量,其值保存在文件中, 所以它可以用于线程也可以用于进程间的同步。
无名信号量,其值保存在内存中。
倘若对信号量没有以上的全面认识的话,你就会很快发现自己在信号量的森林里迷失了方向。
三.内核信号量1.内核信号量的构成内核信号量类似于自旋锁,因为当锁关闭着时,它不允许内核控制路径继续进行。
然而,当内核控制路径试图获取内核信号量锁保护的忙资源时,相应的进程就被挂起。
只有在资源被释放时,进程才再次变为可运行。
只有可以睡眠的函数才能获取内核信号量;中断处理程序和可延迟函数都不能使用内核信号量。
count:相当于信号量的值,大于0,资源空闲;等于0,资源忙,但没有进程等待这个保护的资源;小于0,资源不可用,并至少有一个进程等待资源。
wait:存放等待队列链表的地址,当前等待资源的所有睡眠进程都会放在这个链表中。
sleepers:存放一个标志,表示是否有一些进程在信号量上睡眠。
2.内核信号量中的等待队列(删除,没有联系)上面已经提到了内核信号量使用了等待队列wait_queue来实现阻塞操作。
当某任务由于没有某种条件没有得到满足时,它就被挂到等待队列中睡眠。
当条件得到满足时,该任务就被移出等待队列,此时并不意味着该任务就被马上执行,因为它又被移进工作队列中等待CPU资源,在适当的时机被调度。
内核信号量是在内部使用等待队列的,也就是说该等待队列对用户是隐藏的,无须用户干涉。
由用户真正使用的等待队列我们将在另外的篇章进行详解。
3.内核信号量的相关函数(2)申请内核信号量所保护的资源:4.内核信号量的使用例程在驱动程序中,当多个线程同时访问相同的资源时(驱动中的全局变量时一种典型的共享资源),可能会引发“竞态“,因此我们必须对共享资源进行并发控制。
Linux内核中解决并发控制的最常用方法是自旋锁与信号量(绝大多数时候作为互斥锁使用)。
四.POSIX 信号量与SYSTEM V信号量的比较1.对POSIX来说,信号量是个非负整数。
常用于线程间同步。
而SYSTEM V信号量则是一个或多个信号量的集合,它对应的是一个信号量结构体,这个结构体是为SYSTEM V IPC服务的,信号量只不过是它的一部分。
常用于进程间同步。
2.POSIX信号量的引用头文件是“<semaphore.h>”,而SYSTEM V信号量的引用头文件是“<sys/sem.h>”。
3.从使用的角度,System V信号量是复杂的,而Posix信号量是简单。
比如,POSIX 信号量的创建和初始化或PV操作就很非常方便。
五.POSIX信号量详解1.无名信号量无名信号量的创建就像声明一般的变量一样简单,例如:sem_t sem_id。
然后再初始化该无名信号量,之后就可以放心使用了。
无名信号量常用于多线程间的同步,同时也用于相关进程间的同步。
也就是说,无名信号量必须是多个进程(线程)的共享变量,无名信号量要保护的变量也必须是多个进程(线程)的共享变量,这两个条件是缺一不可的。
注意:在这些函数中,只有sem_post是信号安全的函数,它是可重入函数(a)无名信号量在多线程间的同步无名信号量的常见用法是将要保护的变量放在sem_wait和sem_post中间所形成的上面的例程,到底哪个线程先申请到信号量资源,这是随机的。
如果想要某个特定的顺序的话,可以用2个信号量来实现。
例如下面的例程是线程1先执行完,然后线程2才继续执行,直至结束。
(b)无名信号量在相关进程间的同步说是相关进程,是因为本程序中共有2个进程,其中一个是另外一个的子进程(由fork 产生)的。
本来对于fork来说,子进程只继承了父进程的代码副本,mutex理应在父子进程中是相互独立的两个变量,但由于在初始化mutex的时候,由pshared = 1指定了mutex处于共享内存区域,所以此时mutex变成了父子进程共享的一个变量。
此//open a file and map it into memoryfd = open("log.txt",O_RDWR|O_CREAT,S_IRWXU);write(fd,&zero,sizeof(int));ptr = mmap( NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0 );close(fd);/* create, initialize semaphore */if( sem_init(&mutex,1,1) < 0) //{perror("semaphore initilization");exit(0);}if (fork() == 0){ /* child process*/for (i = 0; i < nloop; i++){sem_wait(&mutex);printf("child: %d\n", (*ptr)++);sem_post(&mutex);}exit(0);}/* back to parent process */for (i = 0; i < nloop; i++){sem_wait(&mutex);printf("parent: %d\n", (*ptr)++);sem_post(&mutex);}exit(0);}2.有名信号量有名信号量的特点是把信号量的值保存在文件中。
这决定了它的用途非常广:既可以用于线程,也可以用于相关进程间,甚至是不相关进程。
(a)有名信号量能在进程间共享的原因由于有名信号量的值是保存在文件中的,所以对于相关进程来说,子进程是继承了父进程的文件描述符,那么子进程所继承的文件描述符所指向的文件是和父进程一样的,当然文件里面保存的有名信号量值就共享了。
(b)有名信号量相关函数说明有名信号量在使用的时候,和无名信号量共享sem_wait和sem_post函数。
区别是有名信号量使用sem_open代替sem_init,另外在结束的时候要像关闭文件一样去关闭这个有名信号量。
(1)打开一个已存在的有名信号量,或创建并初始化一个有名信号量。
一个单一的调用就完成了信号量的创建、初始化和权限的设置。
这里的name不能写成/tmp/aaa.sem这样的格式,因为在linux下,sem都是创建在/dev/shm目录下。
你可以将name写成“/mysem”或“mysem”,创建出来的文件都是“/dev/shm/sem.mysem”,千万不要写路径。
也千万不要写“/tmp/mysem”之类的。
当oflag = O_CREAT时,若name指定的信号量不存在时,则会创建一个,而且后面的mode和value参数必须有效。
若name指定的信号量已存在,则直接打开该信号量,同时忽略mode和value参数。
当oflag = O_CREAT|O_EXCL时,若name指定的信号量已存在,该函数会直接返回error。
(2) 一旦你使用了一信号量,销毁它们就变得很重要。
在做这个之前,要确定所有对这个有名信号量的引用都已经通过sem_close()函数关闭了,然后只需在退出或是退出处理函数中调用sem_unlink()去删除系统中的信号量,注意如果有任何的处理器或是线程引用这个信号量,sem_unlink()函数不会起到任何的作用。
也就是说,必须是最后一个使用该信号量的进程来执行sem_unlick才有效。
因为每个信号灯有一个引用计数器记录当前的打开次数,sem_unlink必须等待这个数为0时才能把name所指的信号灯从文件系统中删除。
也就是要等待最后一个sem_close发生。
(c)有名信号量在无相关进程间的同步前面已经说过,有名信号量是位于共享内存区的,那么它要保护的资源也必须是位于共享内存区,只有这样才能被无相关的进程所共享。
在下面这个例子中,服务进程和客户进程都使用shmget和shmat来获取得一块共享内#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include <stdio.h>#include <semaphore.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#define SHMSZ 27char SEM_NAME[]= "vik";int main(){char ch;int shmid;key_t key;char *shm,*s;sem_t *mutex;//name the shared memory segmentkey = 1000;//create & initialize semaphoremutex = sem_open(SEM_NAME,O_CREAT,0644,1);if(mutex == SEM_FAILED){perror("unable to create semaphore");sem_unlink(SEM_NAME);exit(-1);}//create the shared memory segment with this key shmid = shmget(key,SHMSZ,IPC_CREAT|0666);if(shmid<0){perror("failure in shmget");exit(-1);}//attach this segment to virtual memoryshm = shmat(shmid,NULL,0);//start writing into memorys = shm;for(ch='A';ch<='Z';ch++){sem_wait(mutex);*s++ = ch;sem_post(mutex);}//the below loop could be replaced by binary semaphore while(*shm != '*'){sleep(1);}sem_close(mutex);sem_unlink(SEM_NAME);shmctl(shmid, IPC_RMID, 0);exit(0);}<u>File 2: client.c</u>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include <stdio.h>#include <semaphore.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#define SHMSZ 27char SEM_NAME[]= "vik";int main(){char ch;int shmid;key_t key;char *shm,*s;sem_t *mutex;//name the shared memory segmentkey = 1000;//create & initialize existing semaphoremutex = sem_open(SEM_NAME,0,0644,0);if(mutex == SEM_FAILED){perror("reader:unable to execute semaphore");sem_close(mutex);exit(-1);}//create the shared memory segment with this keyshmid = shmget(key,SHMSZ,0666);if(shmid<0){perror("reader:failure in shmget");exit(-1);}//attach this segment to virtual memoryshm = shmat(shmid,NULL,0);//start readings = shm;for(s=shm;*s!=NULL;s++){sem_wait(mutex);putchar(*s);sem_post(mutex);}//once done signal exiting of reader:This can be replaced by another semaphore*shm = '*';sem_close(mutex);shmctl(shmid, IPC_RMID, 0);exit(0);}六.SYSTEM V信号量这是信号量值的集合,而不是单个信号量。