#Linux#进程间通信# 信号量(semophore)

信号量本质上是一个计数器(不设置全局变量是因为进程间是相互独立的,而这不一定能看到,看到也不能保证++引用计数为原子操作),可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。主要作为进程间以及同一进程内不同线程之间的同步和互斥手段。它和管道有所不同,它不以传送数据为主要目的,它主要是用来保护共享资源(信号量也属于临界资源),使得资源在一个时刻只有一个进程独享。

信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。为了完成这个过程,需要创建一个信号量VI,然后将Acquire Semaphore VI以及Release Semaphore VI分别放置在每个关键代码段的首末端。确认这些信号量VI引用的是初始创建的信号量。

信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域。临界区域是指执行数据更新的代码需要独占式地执行。而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问它,也就是说信号量是用来调协进程对共享资源的访问的。

最简单的信号量是只能取0和1的变量,这也是信号量最常见的一种形式,叫做二进制信号量。而可以取多个正整数的信号量被称为通用信号量。这里主要讨论二进制信号量。

Linux提供两种信号量

  • (1) 内核信号量,由内核控制路径使用 
  • (2) 用户态进程使用的信号量,这种信号量又分为POSIX信号量和SYSTEM V信号量。

 

内核信号量

内核信号量类似于自旋锁,因为当锁关闭着时,它不允许内核控制路径继续进行。然而,当内核控制路径试图获取内核信号量锁保护的忙资源时,相应的进程就被挂起。只有在资源被释放时,进程才再次变为可运行。只有可以睡眠的函数才能获取内核信号量;中断处理程序和可延迟函数都不能使用内核信号量。

内核信号量是struct semaphore类型的对象,它在<asm/semaphore.h>中定义:

/* Please don't access any members of this structure directly */
struct semaphore {
	raw_spinlock_t		lock;
	unsigned int		count;
	struct list_head	wait_list;
};

当某任务由于没有某种条件没有得到满足时,它就被挂到等待队列中睡眠。当条件得到满足时,该任务就被移出等待队列,此时并不意味着该任务就被马上执行,因为它又被移进工作队列中等待CPU资源,在适当的时机被调度。内核信号量是在内部使用等待队列的,也就是说该等待队列对用户是隐藏的,无须用户干涉。

void down(struct semaphore *sem)
{
    unsigned long flags;

    raw_spin_lock_irqsave(&sem->lock, flags);
    if (likely(sem->count > 0))
        sem->count--;
    else
        __down(sem);//挂到等待队列中睡眠
    raw_spin_unlock_irqrestore(&sem->lock, flags);
}

 

 

用户态进程信号量

 

POSIX信号量

Posix是“可移植操作系统接口(Portable Operating System Interface )的首字母简写,但它并不是一个单一的标准,而是一个电气与电子工程学会即IEEE开发的一系列标准,它还是由ISO(国际标准化组织)和IEC(国际电工委员会)采纳的国际标准。Posix标准正变得越来越流行,很多厂家开始采用这一标准。渐渐有取代SYSTEM V信号量的趋势。

Posix信号量是基于内存的,即信号量值是放在共享内存中的,它是由可能与文件系统中的路径名对应的名字来标识的。

有名信号量:  放在共享内存区中由文件系统中的路径名对应的名字来标识, 一般用于进程同步。也可以用于线程,甚至是不相关进程。类似有名管道。由于有名信号量的值是保存在文件中的,所以对于相关进程来说,子进程是继承了父进程的文件描述符,那么子进程所继承的文件描述符所指向的文件是和父进程一样的,当然文件里面保存的有名信号量值就共享了。

无名信号量:  存放在共享内存区中,一般用于线程同步。同时也用于相关进程间的同步。也就是说,无名信号量必须是多个进程(线程)的共享变量,无名信号量要保护的变量也必须是多个进程(线程)的共享变量,这两个条件是缺一不可的。类似无名管道。

 

SYSTEM V信号量

System v是Unix操作系统众多版本的一个分支,它最初是由AT&T在1983年第一次发布,System v一共有四个版本,而最成功的是System V Release 4,或者称为SVR4。这样看来,一个是Unix 的标准之一(另一个标准是Open Group),一个是Unix众多版本的分支之一(其他的分支还有Linux跟BSD)。PV操作,是狄克斯特拉荷兰文定义的,因为在荷兰文中,通过叫passeren,释放叫vrijgeven,PV操作因此得名。这是在计算机术语中不是用英语表达的极少数的例子之一。

System v信号量测试基于内核的,它放在内核里面。

System v是信号量值的集合,而不是单个信号量。相关的信号量操作函数由<sys/ipc.h>引用。system V 信号量在内核中维护,其中包括二值信号量 、计数信号量、计数信号量集。

  • 1. 二值信号量(binary  semaphore):其值或为0或为1的信号量。这与互斥锁类似,若资源被锁住则信号量值为0,若资源可用则信号量值为1。
  • 2. 计数信号量(counting semaphore):其值为0和某个限制值(对于Posix信号量,该值必须至少为32767)之间的信号量。该信号量的值就是可用资源数。
  • 以上这两种类型的信号中,等待(wait)操作都等待信号量的值变为大于0,然后将它减1。挂出(post)操作则是将信号量的值加1。从而唤醒正在等待该信号量值变为大于0的任意线程。
  • 3. 计数信号量集(set of counting semaphore):一个或者多个信号量(构成一个集合),其中每个都是计数信号量。每个集合的信号量数都存在一个限制,一般在25个的数量级。

 

信号量(semophore)分System V标准与POSIX 标准,详细参考

#Linux#进程间通信# System V标准&POSIX标准

发布了170 篇原创文章 · 获赞 207 · 访问量 459万+

猜你喜欢

转载自blog.csdn.net/xiaoting451292510/article/details/103731012