2024年9月信号量wait和signal(记录型信号量)
⑴信号量wait和signal(记录型信号量
⑵记录型信号量:需要一个用于代表资源数目的整型变量value外,还应增加一个进程链表L,用于链接等待进程。两个数据项可描述为:typesemaphore=record??????????????value:integer;??????????????L:listofprocess;??????????????end??????????????图相应地,wait(S)和signal(S)操作可描述为:procedurewait(S)?????varS:semaphore;?????begin????????S.value:=S.value-;????????ifS.value《thenblock(S,L)?????Endproceduresignal(S)?????varS:semaphore;?????begin????????S.value:=S.value+;????????ifS.value≤thenwakeup(S,L);?????end在记录型信号量机制中,S.value的初值表示系统中某类资源的数目,因而又称为资源信号量,对它的每次wait操作,意味着进程请求一个单位的该资源,因此描述为S.value:=S.value-;当S.value《时,表示该类资源已分配完毕,因此进程应调用block原语,进行自我阻塞,放弃处理机,并插入到信号量链表S.L中。可见,该机制遵循了“让权等待”准则。此时S.value的绝对值表示在该信号量链表中已阻塞进程的数目。对信号量的每次signal操作,表示执行进程释放一个单位资源,故S.value:=S.value+操作表示资源数目加.若加后仍是S.value≤,则表示在该信号量链表中,仍有等待该资源的进程被阻塞,故还应该调用wakeup原语,将S.L链表中的第一个等待进程唤醒。如果S.value的初值为,表示只允许一个进程访问临界资源,此时的信号量转化为互斥信号量。??以上内容摘之《计算机操作系统》,下面我谈谈对记录型信号量的认识:如上图,你看上去是不是很像我们学习过的C语言定义的数据结构,它就是因此而得名的。只不过它是pascal语言书写的而已,那看下面两个方框,一个是wait,另一个是signal,是不是很像咱学的C语言啊。每次wait操作就是给进程分配一个单位的资源,每次signal操作就是进程释放一个单位资源。???现在我们假设我的电脑有两台打印机,所以S.value的初值为,表示系统打印机的数目,称为资源信号量。进程A请求打印,那么系统对它执行一次wait操作,执行S.value:=S.value-语句后S.value减,S.value的值变为,表示有一个资源空闲。执行if语句,S.value不小于,结束。然后又来了一个进程B请求打印,系统对它又执行一次wait操作,执行S.value:=S.value-语句后S.value减,S.value的值变为,表示没有空闲的资源。执行if语句,S.value不小于,结束。又来一个进程C请求打印,系统对它又执行一次wait操作,执行S.value:=S.value-语句后S.value减,S.value的值变为-,表示有一个进程没有得到打印机资源。执行if语句,S.value小于,执行block(S,L),进行自我阻塞,放弃处理机,并插入到信号量链表S.L中。此时S.value的绝对值表示了在该信号量链表中已阻塞进程的数目。所以这个时候阻塞的进程为一个,即是进程C。???系统运行了一段时间后,A进程结束,在结束前执行了signal操作,当执行到S.value:=S.value+语句时,S.value加,即S.value变为.然后执行if语句,S.value小于等于,执行wakeup(S,L),从S.L链表中唤醒C进程。过了一会,B进程结束,同样执行signal操作,S.value变为,表示有一个资源空闲。紧接着C进程也结束了,S.value变为。S.value最终等于初值,等待其他的进程进行资源请求。
⑶整型信号量的物理含义
⑷Dijkstra把整型信号量定义为一个整形量,除初始化外,通过两个标准的原子操作(AtomicOperation)wait(s)和signal(s)来访问.这两个操作很长时间以来,一直被分别称为P、v操作.wait和signal操作可描述为:wait(s):whiles≤dono_op:s:=s-;signal(s):s:=s+;wait(s)和signal(s)是两个原子操作,因此,它们在执行时是不可中断的.亦即产生一个进程在修改某信号量时,没有其他进程可同时对该信号量进行修改.此外,在wait操作中,对s值的测试和做s:=s-操作时,都不可中断.信号量的物理意义如下:()若信号量s为正值,则该值等于在封锁进程之前对信号量s可施行的P操作数,亦即等于s所代表的实际使用的物理资源个数.()若信号量s为负值,则其绝对值等于登记排列在该信号量s队列之中等待进程的个数,亦即恰好等于对信号量s实施P操作而被封锁起来并进入信号量s队列的进程数.()通常P操作意味着请求一个资源,V操作意味着释放一个资源.在一定条件下,P操作代表挂起进程操作,而V操作代表唤醒被挂起进程的操作.
⑸(计算机操作系统wait操作和signal操作什么意思
⑹sem_wait是一个函数,也是一个原子操作,它的作用是从信号量的值减去一个“”,但它永远会先等待该信号量为一个非零值才开始做减法。也就是说,如果你对一个值为的信号量调用sem_wait(),线程将会继续执行,将信号量的值将减到。
⑺如果对一个值为的信号量调用sem_wait(),这个函数就会原地等待直到有其它线程增加了这个值使它不再是为止。如果有两个线程都在sem_wait()中等待同一个信号量变成非零值。
⑻那么当它被第三个线程增加一个“”时,等待线程中只有一个能够对信号量做减法并继续执行,另一个还将处于等待状态。sem_trywait(sem_t*sem)是函数sem_wait的非阻塞版,它直接将信号量sem减,同时返回错误代码。
⑼sig是传递给signal的唯一参数。执行了signal()调用后,进程只要接收到类型为sig的信号,不管其正在执行程序的哪一部分,就立即执行func()函数。当func()函数执行结束后,控制权返回进程被中断的那一点继续执行。
⑽signal()会依参数signum指定的信号编号来设置该信号的处理函数。当指定的信号到达时就会跳转到参数handler指定的函数执行。
⑾当一个信号的信号处理函数执行时,如果进程又接收到了该信号,该信号会自动被储存而不会中断信号处理函数的执行,直到信号处理函数执行完毕再重新调用相应的处理函数。但是如果在信号处理函数执行时进程收到了其它类型的信号,该函数的执行就会被中断。
⑿signal操作的注意点:
⒀不要使用低级的或者STDIO.H的IO函数
⒁不是浮点信号的时候不要用longjmp
⒂signal函数是由ISOC定义的。因为ISOC不涉及多进程,进程组以及终端I/O等,所以他对信号的定义非常含糊,以至于对UNIX系统而言几乎毫无用处。
⒃参考资料来源:百度百科-signal
⒄参考资料来源:百度百科-sem_wait
⒅若wait、signal操作的信号量S初值为,当前值为-,则表示有(个进程等待.a.b.c..d.
⒆如果计算机*作系统中,若P、V*作的信号量S初值为,当前值为-,则表示有____个等待进程信号量表示的是可用的资源数。初值为,表示初始时有两个可用的资源。现在为-,说明这两个可用资源已经被占用了,而且有一个进程在等待资源,所以就为-了
⒇信号量机制和PV操作
⒈进程管理中,对临界资源需要互斥访问。其中对实现对临界区互斥访问有软件和硬件方法。是一个变量,一个信号量对应一种资源,只能被两种PV两种原语操作,以此实现进程互斥,进程同步。(PV源于荷兰语proberen和verhogen分别是尝试试用和增加的意思补充:原语是一种特殊的程序段,不可被中断。原语是由关中断/开中断指令来实现的。wait()//进入区访问临界资源//临界区signal()//退出区然后对于整型信号量种的pv操作原语wait和signal分别实现逻辑是:对于记录型信号量:一个信号量对应一种资源信号量的值=这种资源的剩余数量(若为负,说明此时有进程在等待这种资源一前一后的操作同步量信号S,初始为在前操作之后执行V在后操作之后执行P口诀:前v后p如上pv操作本质上是多级同步问题缓冲区的这种临界资源只能互斥访问p尝试消耗v增加所以实现互斥的p操作一定要在实现同步的P操作之后。v操作不会导致进程阻塞,因此两个v操作顺序可以交换。一个生产者生产多类产品缓冲区不会消耗掉封装思想
⒉为了两个进程可以同步进行至少需要哪两个信号量
⒊wait和signal是原子操作,不是信号量,但它们操作的对象是信号量。wait和signal对应于传统的P和V操作。P操作请求一个信号量,对信号量做减一操作;V操作释放一个信号量,对信号量做加一操作。你指的生产者消费者问题中,full和empty是把信号量作为“信号”使用的。当wait(full)返回后,意味着缓冲池中被填充了一个产品,这时候消费者可以取走一个产品。实际上我觉得这里用“filled“代替“full“,可读性会更好。为了同步两个进程,至少需要个信号量。
⒋为什么在wait和signal操作中对信号量s的访问必须互斥执行
⒌因为在执行时是不可中断的,且必须成对出现。缺少wait导致系统混乱,不能保证对临界资源的互斥访问,缺少signal将会使临界资源永远不被释放,导致等待该资源的进程不被唤醒。
⒍整形信号量中wait和signal操作是什么意思
⒎wait和signal是操作系统的原子操作把S定义为整形信号量wait(s)//用于申请资源whiles《=dono-op;//整形信号量值《=时循环执行空操作s=s-//wait操作S值减一signal(s)//用于释放资源S=S+//signal操作S值加一
⒏信号量是包含一个非负整数型的变量,并且带有两个原子操作wait和signal。Wait还可以被称为down、P或lock,signal还可以被称为up、V、unlock或post。在UNIX的API中(POSIX标准用的是wait和post。
⒐对于wait操作,如果信号量的非负整形变量S大于,wait就将其减,如果S等于,wait就将调用线程阻塞;对于post操作,如果有线程在信号量上阻塞(此时S等于,post就会解除对某个等待线程的阻塞,使其从wait中返回,如果没有线程阻塞在信号量上,post就将S加.
⒑由此可见,S可以被理解为一种资源的数量,信号量即是通过控制这种资源的分配来实现互斥和同步的。如果把S设为,那么信号量即可使多线程并发运行。另外,信号量不仅允许使用者申请和释放资源,而且还允许使用者创造资源,这就赋予了信号量实现同步的功能。可见信号量的功能要比互斥量丰富许多。
⒒POSIX信号量是一个sem_t类型的变量,但POSIX有两种信号量的实现机制:无名信号量和命名信号量。无名信号量只可以在共享内存的情况下,比如实现进程中各个线程之间的互斥和同步,因此无名信号量也被称作基于内存的信号量;命名信号量通常用于不共享内存的情况下,比如进程间通信。
⒓同时,在创建信号量时,根据信号量取值的不同,POSIX信号量还可以分为:
⒔下面是POSIX信号量函数接口:
⒕信号量的函数都以sem_开头,线程中使用的基本信号函数有个,他们都声明在头文件semaphore.h中,该头文件定义了用于信号量操作的sem_t类型:
⒖【sem_init函数】:
⒗该函数用于创建信号量,原型如下:
⒘该函数初始化由sem指向的信号对象,设置它的共享选项,并给它一个初始的整数值。pshared控制信号量的类型,如果其值为,就表示信号量是当前进程的局部信号量,否则信号量就可以在多个进程间共享,value为sem的初始值。
⒙该函数调用成功返回,失败返回-。
⒚【sem_destroy函数】:
⒛该函数用于对用完的信号量进行清理,其原型如下:
成功返回,失败返回-。
【sem_wait函数】:
该函数用于以原子操作的方式将信号量的值减。原子操作就是,如果两个线程企图同时给一个信号量加或减,它们之间不会互相干扰。其原型如下:
sem指向的对象是sem_init调用初始化的信号量。调用成功返回,失败返回-。
sem_trywait()则是sem_wait()的非阻塞版本,当条件不满足时(信号量为时,该函数直接返回EAGAIN错误而不会阻塞等待。
sem_timedwait()功能与sem_wait()类似,只是在指定的abs_timeout时间内等待,超过时间则直接返回ETIMEDOUT错误。
【sem_post函数】:
该函数用于以原子操作的方式将信号量的值加,其原型如下:
与sem_wait一样,sem指向的对象是由sem_init调用初始化的信号量。调用成功时返回,失败返回-。
【sem_getvalue函数】:
该函数返回当前信号量的值,通过restrict输出参数返回。如果当前信号量已经上锁(即同步对象不可用,那么返回值为,或为负数,其绝对值就是等待该信号量解锁的线程数。
之所以称为命名信号量,是因为它有一个名字、一个用户ID、一个组ID和权限。这些是提供给不共享内存的那些进程使用命名信号量的接口。命名信号量的名字是一个遵守路径名构造规则的字符串。
【sem_open函数】:
该函数用于创建或打开一个命名信号量,其原型如下:
参数name是一个标识信号量的字符串。参数oflag用来确定是创建信号量还是连接已有的信号量。
oflag的参数可以为,O_CREAT或O_EXCL:如果为,表示打开一个已存在的信号量;如果为O_CREAT,表示如果信号量不存在就创建一个信号量,如果存在则打开被返回,此时mode和value都需要指定;如果为O_CREAT|O_EXCL,表示如果信号量存在则返回错误。
mode参数用于创建信号量时指定信号量的权限位,和open函数一样,包括:S_IRUSR、S_IWUSR、S_IRGRP、S_IWGRP、S_IROTH、S_IWOTH。
value表示创建信号量时,信号量的初始值。
【sem_close函数】:
该函数用于关闭命名信号量:
单个程序可以用sem_close函数关闭命名信号量,但是这样做并不能将信号量从系统中删除,因为命名信号量在单个程序执行之外是具有持久性的。当进程调用_exit、exit、exec或从main返回时,进程打开的命名信号量同样会被关闭。
【sem_unlink函数】:
sem_unlink函数用于在所有进程关闭了命名信号量之后,将信号量从系统中删除:
【信号量操作函数】:
与无名信号量一样,操作信号量的函数如下:
命名信号量是随内核持续的。当命名信号量创建后,即使当前没有进程打开某个信号量,它的值依然保持,直到内核重新自举或调用sem_unlink()删除该信号量。
无名信号量的持续性要根据信号量在内存中的位置确定:
很多时候信号量、互斥量和条件变量都可以在某种应用中使用,那这三者的差异有哪些呢?下面列出了这三者之间的差异:
信号量:二进位信号量和计数信号量
信号量(semaphore是一个被线程共享的非负变量。信号量是一个发信号的机制。一个等待一个信号量的线程可以被其他线程通知(signal。这个机制通过wait和signal两个原子操作(atomicoperations来实现进程同步。一个信号量要么允许访问资源,要么不允许访问资源。二者只能选其一。而具体是哪一种,则要看设置。下面是信号量的一些特点:最常见的两种信号量:这种信号量用一个计数来帮助任务被获取(beacquired或释放(bereleased数次。具体机制如下图所示:二进位信号量和计数信号量非常相似,但是他们的计数值只能限制在和两个数字。在这种信号量下,等待(wait操作只能在信号量等于(semaphore=时工作。而通知(signal操作只有在信号量等于(semaphore=时才能成功。二进位信号量的实现要比计数信号量的实现要简单。信号量的等待操作(waitoperation和通知操作(signaloperation是用来实现同步的。信号量操作的不得是为了互相独立。等待操作(waitoperation用来帮助我们控制任务是否可以进入关键的部分。当信号量是正的时候,信号量将被减一。如果当信号量为负数或者零的时候,等待操作不执行任何操作。当信号量被递减后,信号量值为负数或者零时,该指令将被挂起保持,直到信号量重新满足大于的条件。通知操作(signaloperation是用于控制一个任务退出某个重要部分。当信号量的值是负的时候,信号量将被加一。下面列举了计数信号量和二进位信号量的主要不同: