精华内容
下载资源
问答
  • 信号量上面值n代表什么意思呢? n>0:当前有可用资源,可用资源数量n n=0:资源都被占用,可用资源数量为0 n<0:资源都被占用,并且还有n个进程正在排队 那信号量拖着的那个队列就是用来放正在排队想要...

    信号量是什么

    信号量(semaphore)是操作系统用来解决并发中的互斥和同步问题的一种方法。
    信号量是一个与队列有关的整型变量,你可以把它想象成一个数后面拖着一条排队的队列,如图:

    在这里插入图片描述
    那信号量上面值n代表什么意思呢?
    n>0:当前有可用资源,可用资源数量为n
    n=0:资源都被占用,可用资源数量为0
    n<0:资源都被占用,并且还有n个进程正在排队
    那信号量拖着的那个队列就是用来放正在排队想要使用这一资源的进程

    信号量伪代码

    信号量的伪代码又如何实现呢
    在这里插入图片描述
    在代码中我们可以看到有两个对信号量的count值和阻塞队列的操作,一个是semWait,一个是semSignal,前者也被称为P操作,后者也被称为V操作。

    这两个操作的用途是什么呢?
    semWait我们可以理解为申请资源
    semSignal我们可以理解为释放资源

    在这里插入图片描述
    当申请资源的时候,资源数count值-1,我们注意到资源数如果在-1之后<0,那么这个这个进程就会加入到等待队列

    为什么这个条件设置成<0呢?
    其实很好理解,当这个资源已经其他进程占有完了,即为0或者负数,那么新进程要申请这个资源时资源数再减1必然count<0,那么这个进程就要被被阻塞,进入阻塞队列
    在这里插入图片描述

    再看semSignal操作
    在这里插入图片描述
    一个进程终会使用完这个进程,然后离开,那么此时可用资源数+1

    为什么这个条件设置成<=0呢?
    一个进程用完资源走了,count++,如果还有进程在排队(count即值是-1或者更小),那+1之后必然count<=0,此时就唤醒一个排队中的进程
    在这里插入图片描述

    信号量解决互斥同步问题

    用一个经典例子来说——生产者/消费者问题
    在这里插入图片描述

    1. 首先我们分析这里有几种进程,很显然有两种:
    • 消费者
    • 生产者
    1. 分析进程之间的关系有什么:
    • 互斥关系:缓冲区是临界资源,各进程互斥访问

    • 两组同步关系
      只有缓冲区未满,生产者才能往缓冲区放产品
      只有缓冲区非空,消费者才能从缓冲区取产品

    1. 根据以上分析,写出大致的伪代码如下:

    在这里插入图片描述

    总结

    • semWait(S):请求分配一个资源。

    • semSignal(S):释放一个资源。

    • semWait、semSignal操作必须成对出现。

    1. 用于互斥时,位于同一进程内(初始值为1);
    2. 用于同步时,交错出现于两个合作进程内。
      (且在前事件后加semSignal,在后事件前加semWait),比如先刷牙再吃饭,那刷牙这个事件后加semSignal,在吃饭这个事件前加semWait
    • 多个semWait操作的次序不能颠倒,否则可能导致死锁。

    • 多个semSignal操作的次序可任意。

    展开全文
  • 信号量

    万次阅读 多人点赞 2017-03-10 20:44:41
    一、首先:我们要知道信号量什么?  信号量的本质是数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识。信号量在此过程中...

    一、首先:我们要知道信号量是什么?

           信号量的本质是数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识。信号量在此过程中负责数据操作的互斥、同步等功能。

    这是书本上介绍的信号量的概念,自己的理解比较简单:

         信号量就是具有原子性的计数器,就相当于一把锁,在每个进程要访问临界资源时,必须要向信号量拿个锁”,它才能进去临界资源这个“房间”,并锁上门,不让其他进程进来,此时信号量执行P()操作,锁的数目减少了一个,所以计数器减1,;当它访问完成时,它出来,将锁还给信号量,执行V()操作,计数器加1;然后是下面的进程继续。这也体现了各个进程访问临时资源是互斥的。

    “原子性”:表示的是一件事情的两种状态,做了这件事和没做这件事;

    “计数器”:信号量通常描述的是临界资源的数目;同时信号量本身就是临界资源,它的目的也是保护临界资源,解决数                 据不一致问题;

    “临界资源”:不同进程可以看到的那份共同的资源;

    “临界区”:多个进程访问临界资源的代码;

    “互斥”:任何时刻,只允许一个临时区访问临时资源,并且属性是原子的。


    二、我们为什么要使用信号量

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


    三、写出程序实例

          让两个进程分别向显示器(linux下一切皆文件,临界资源)打印AA和BB,当没有信号量进行保护时,会出现数据混乱,例如:“AABBABAAAB...”,为了解决这一问题,我们创建信号量进行保护。打印“AA”或“BB”。

     我们要写出代码接口:

    创建信号量 creat_sems:


    key:ftok函数生成


    第一个参数_key,为整型值,是允许其他的进程访问信号量的一个整型的变量。所以的信号都是通过间接的方式获得的,运行的程序会提供一个信号的键值,系统为每一个键值赋予一个信号量,其他的处理函数只能通过对semget函数的返回值进行处理。

    第二个参数_nsems,参数表示信号量的编号,几乎总是取值为1.

    第三个参数_semflg,信号量的权限。

    打开和存取操作与参数semflg中的内容相关。IPC_CREAT如果信号量集在系统内核中不存在,则创建信号量集。IPC_EXCL当和 IPC_CREAT一同使用时,如果信号量集已经存在,则调用失败。如果单独使用IPC_CREAT,则semget()要么返回新创建的信号量集的标识符,要么返回系统中已经存在的同样的关键字值的信号量的标识符。如果IPC_EXCLIPC_CREAT一同使用,则要么返回新创建的信号量集的标识符,要么返回-1IPC_EXCL单独使用没有意义。参数nsems指出了一个新的信号量集中应该创建的信号量的个数。


    销毁信号量destory_sems()


    功能:控制信号量的信息

    返回值:成功返回0,失败返回-1

    第一个参数semid:信号量标识码,还是通过semget来获得的,是semget函数的一个返回值

    第二个参数semnum:信号量的编号,当用到信号量数组的时候,这个编号就会起到作用

    第三个参数cmd:为允许的命令

    第四个参数是个联合体:


    初始化信号量init_sem()

    与销毁信号量所用函数相同,但参数不同


    p、v操作:


    函数功能:用户改变信号量的值.

    返回值:函数调用成功返回0,失败返回-1

    参数semid:系统分配给该信号量的一个ID号,通过semget函数的返回值来获得,也称为信号的标识码

    参数sops:一个指向信号量结构体数组的指针,信号量的结构体至少有3个成员。

    nsops:进行操作信号量的个数,即sops结构变量的个数,需大于或等于1。最常见设置此值等于1,只完成对一个信号量的操作

    注意这里的结构体sembuf


    struct sembuf

    {

    unsigned short sem_num;操作信号在信号集中的编号,第一个信号的编号为0,第二个为1,一次后推

    short sem_op;信号资源,如果有就分配,如果为负值就等待(wait),如果正值就分配信号资源

    short sem_flg;信号操作标志,有两种状态,一个是SEM_UNDO,另一个是SEM_NOWAIT

    }

    SEM_NOWAIT//对信号的操作不能满足是,semop()函数就会阻塞,并立即返回,同时设置错误信息。

    SEM_UNDO//程序结束时(无论是否正常结束),保证信号值会被重新设为semop()调用前的值。这样做

    的目的在于避免在异常情况下结束时未将锁定资源解锁,造成该资源永远锁定。


    flag一般为0,若flag包含IPC_NOWAIT,则该操作为非阻塞操作。若flag包含SEM_UNDO,则当进程退出的时候会还原该进程的信号量操作,这个标志在某些情况下是很有用的,比如某进程做了P操作得到资源,但还没来得及做V操作时就异常退出了,此时,其他进程就只能都阻塞在P操作上,于是造成了死锁。若采取SEM_UNDO标志,就可以避免因为进程异常退出而造成的死锁。


    下面写一个小例子声明一个结构体:

     struct sembuf sem1_opt_wakeup[1]={0,1,SEM_UNDO};

     struct sembuf sem1_opt_wait[1]={1,-1,SEM_UNDO};


        只有将 sem_flg 指定为 SEM_UNDO 标志后,semadj (所指定信号量针对调用进程的调整值)才会更新。   此外,如果此操作指定SEM_UNDO,系统更新过程中会撤消此信号灯的计数(semadj)。此操作可以随时进行---它永远不会强制等待的过程。调用进程必须有改变信号量集的权限。


    验证信号量的实例:

    comn.h文件


    comn.c文件:

    各函数接口


    test_sems测试文件


    展开全文
  • Linux 信号量

    千次阅读 2017-08-19 18:20:49
    信号量信号量主要用于进程和线程间的同步,信号量保存一个整数值来控制对资源的访问,当值大于0时,表示资源空闲可以访问,等于0表示资源分配完毕无法访问,小于0表示有至少1个线程(进程)正在等待资源。...

    信号量

    信号量主要用于进程和线程间的同步,信号量保存一个整数值来控制对资源的访问,当值大于0时,表示资源空闲可以访问,等于0时表示资源分配完毕无法访问,小于0时表示有至少1个线程(进程)正在等待资源。如果信号量的值只为0或1,那么它就是一个二元信号量,功能就想当于一个互斥锁。

    信号量的P,V操作

    信号量只有两种操作:等待和发送信号,分别用P(s), V(s)表示。P,V操作是不可分割的。

    P(s): 如果s的值大于0,那么P将s的值减1。如果s为0,那么就挂起这个线程知道s变为非零。一个V操作会唤醒这个线程。

    V(s):将s加1,如果有线程等待s变为非0,那么唤醒该线程,该线程将s减1。

    函数解析

    信号量有两种实现:System V信号量和Posix信号量,System V信号量由semget、semop、semctl这几个函数来实现,具体参考: System V信号量函数。下面重点介绍Posix的信号量函数。

    #include<semaphore.h>    包含在头文件
    int sem_init(sem_t *sem, int pshared, unsigned int value)
        sem:要初始化的信号量;
        pshared:此信号量是在进程间共享还是线程间共享,0则为线程共享;
        value:信号量的初始值;
        成功时返回 0;错误时,返回 -1,并把 errno 设置为合适的值
    
    int sem_destroy(sem_t *sem)
        sem是要销毁的信号量。
        只有用sem_init初始化的信号量才能用sem_destroy销毁。
        成功时返回 0;错误时,返回 -1,并把 errno 设置为合适的值
    
    int sem_wait(sem_t *sem)
        等待信号量,如果信号量的值大于0,将信号量的值减1,立即返回。
        如果信号量的值为0,则线程阻塞。相当于P操作。
        成功时返回 0;错误时,返回 -1,并把 errno 设置为合适的值
    
    int sem_post(sem_t *sem)
        释放信号量,让信号量的值加1。相当于V操作。
        成功时返回 0;错误时,返回 -1,并把 errno 设置为合适的值

    Linux线程的信号量同步

    信号量处理生产者消费者问题

    #include <stdlib.h>
    #include <stdio.h>
    #include <pthread.h>
    #include <semaphore.h>
    #include <unistd.h>
    
    struct buffer
    {
      char data[20];
      int n;  //number of product in data
      int p; //index of producer
      int c; //index of consumer
      buffer():n(20),p(-1),c(-1){}
    };
    
    int bk = 1;
    buffer mybuf;
    sem_t mutex, prod, cons;  // three semaphore 
    
    void* producer_thread(void* arg)
    {
      char ch = 'A';
      while(bk)
      {
        sem_wait(&prod);    //can produce
        sem_wait(&mutex);  //mutex the buff
        mybuf.data[(++mybuf.p)%mybuf.n] = ch;
        sem_post(&mutex);
        sem_post(&cons);   //tell consumer there is new product
        printf("%lu produce: %c\n", pthread_self(), ch);
        if(ch>='Z')
          ch = 'A';
        else
          ch = ch + 1;
        sleep(1);   //relax
      }
      return NULL;
    }
    
    void* consumer_thread(void* arg)
    {
      char ch;
      while(bk)
      {
        sem_wait(&cons);  //wait for product 
        sem_wait(&mutex);
        ch = mybuf.data[(++mybuf.c)%mybuf.n];
        sem_post(&mutex);
        sem_post(&prod);  //tell producer there is a new buff to produce
        printf("%lu consume: %c\n", pthread_self(), ch);
        sleep(2);  //digest
      }
      return NULL;
    }
    
    int main()
    {
      pthread_t pidp[5];
      pthread_t pidc[5];
      sem_init(&mutex, 0, 1);
      sem_init(&cons, 0, 0);    //at the begin there is 0 product ot consume
      sem_init(&prod, 0, 20);   //at the begin there are 20 product to produce
    
      for(int i=0; i<3; i++)
        pthread_create(&pidp[i], NULL, producer_thread, NULL);
    
      for(int i=0; i<3; i++)
        pthread_create(&pidc[i], NULL, consumer_thread, NULL);
    
      sleep(10);
      bk = 0;   //after 60s, stop the will
      int x = 3;
      while(x)
      {
        sem_post(&prod);
        printf("prod----\n");
        x--;
      }
      x = 3;
      while(x)
      {
        printf("cons----\n");
        sem_post(&cons);
        x--;
      }
    
      for(int i=0; i<3; i++)
        pthread_join(pidp[i], NULL);
    
      for(int i=0; i<3; i++)
        pthread_join(pidc[i], NULL);
    
      sem_destroy(&mutex);
      sem_destroy(&cons);
      sem_destroy(&prod);
      printf("finished\n");
      return 0;
    }

    信号量实现生产者消费者问题

    信号量与互斥锁条件变量的区别

    信号量与线程锁、条件变量相比有以下几点不同:
    1. 锁必须是同一个线程获取以及释放,否则会死锁。而条件变量和信号量则不必。
    2. 信号的递增与减少会被系统自动记住,系统内部有一个计数器实现信号量,不必担心会丢失,而唤醒一个条件变量时,如果没有相应的线程在等待该条件变量,这次唤醒将被丢失。
    3. 信号量可以允许多个线程访问资源,互斥锁一个时刻只有一个线程访问资源。

    展开全文
  • 信号量机制

    千次阅读 2018-09-27 11:51:40
    *信号量定义一个整型量; *根据初始情况赋相应的值; *仅能通过两个原子操作来访问。 P操作 wait(S): While S&lt;=0 do no-op; S:=S-1; V操作 signal(S): S:=S+1; 2)记录型信号量 *整型信号量符合“有限...

    荷兰科学家Dijkstra(狄克斯特拉)提出的一种卓有成效的进程同步机制

    1) 整型信号量
    *信号量定义为一个整型量;
    *根据初始情况赋相应的值;
    *仅能通过两个原子操作来访问。

    P操作 wait(S):
    While S<=0 do no-op;
    S:=S-1;
    V操作 signal(S):
    S:=S+1;

    2)记录型信号量
    *整型信号量符合“有限等待”原则
    signal释放资源后,当CPU被分配给等待进程后,等待进程仍可继续执行,可以符合“有限等待”。

    *但整型信号量不符合“让权等待”原则
    整型信号量的wait操作,当s ≤0时,当前进程会占着CPU不断测试;
    信号量原语不能被打断,这个占有CPU的进程会一直不断的占据CPU循环下去,陷入忙等。

    • 信号量结构信息发生变化

    *不仅要有值的处理,还有队列的处理。

    *此时形成记录型数据结构,包括两部分:
    *整型变量value(代表资源数目)
    *进程链表L(链接所有等待进程):

    *代码描述:
    type Semaphore=record
    value:integer;
    L:list of PCB;
    end;
    操作:S.Value,S.L

    Value>0,表示当前可用资源的数量;
    Value≤0,其绝对值表示等待使用该资源的进程数,即在该信号量队列上排队的PCB的个数。

    P、V操作也有所变化
    不仅修改资源数,还要处理进程的阻塞、唤醒等操作。

    P操作wait():
    S.value = S.value - 1;
    if S.value < 0 then block(S,L)

    V操作signal():
    S.value = S.value + 1;
    if S.value <= 0 then wakeup(S,L)

    *定义信号量semaphore代表可用资源实体的数量。又叫信号灯。
    *当≥0,代表可供并发进程使用的资源实体数
    *当<0,表示正在等待使用该资源的进程数。

    *建立一个信号量必须经过说明,包括
    *信号量所代表的意义
    *赋初值
    *建立相应的数据结构,以便指向等待使用临界区的进程。

    *除初值外,信号量的值仅能由标准原子操作P、V操作来改变。 PV操作是荷兰语通过和释放的意思。

    3)信号量的基本应用

    *实现进程互斥
    *实现进程间的前趋关系(有序)

    互斥信号量注意点:
    1.互斥信号量mutex初值为1;
    2.每个进程中将临界区代码置于P(mutex)和V(mutex)原语之间
    3.必须成对使用P和V原语(在同一进程中),不能次序错误、重复或遗漏:
    *遗漏P原语则不能保证互斥访问
    *遗漏V原语则不能在使用临界资源之后将其释放(给其他等待的进程);

    实现有序

    *前趋关系:
    并发执行的进程P1和P2中,分别有代码C1和C2,要求C1要在C2开始前完成;

    *为每对前趋关系设置一个同步信号量S12,并赋初值为0。则只有V操作所在进程获得cpu时能运行。

    如图:
    在这里插入图片描述

    控制同步顺序的注意点

    *信号量值为0的点是限制的关键所在;
    *成对使用P和V原语(在有先后关系的两个进程中),不能次序错误、重复或遗漏,否则同步顺序出错。

    4)AND型信号量
    *出现原因:一些应用往往需要两个或多个共享资源,而不是前述的一个资源。进程同时要求的共享资源越多,发生死锁可能性越大。
    在这里插入图片描述
    *解决思想:
    一次性分配给进程所需资源,用完一起释放。Wait操作时对它所有需要的资源都要判断,有AND条件,故称“AND同步”、“同时wait”。

    Swait(S1, S2, …, Sn)
    if (S1 >=1 and … and Sn>=1 )then
    for i:=1 to n do
    Si:= Si -1 ;
    endfor
    else
    将进程阻塞在第一个不能满足资源信号量的队列中。
    endif

    Ssignal(S1, S2, …, Sn)
    for i:=1 to n do
    Si:= Si +1 ;
    唤醒所以与si相关的阻塞进程
    endfor

    5)信号量集

    引入原因:
    *每次只能获得或释放一个单位的资源,低效;
    *某些时候资源分配有下限的限制;
    *修改:在大于可分配设置的下界值t前提下,每次可分配d个。

    AND信号量机制上加以扩充,每种资源参数有三:
    S 为信号量(现有值);
    t 为下限值(现有不能少于该条件);
    d 为需求值;

    Swait(S1, t1, d1, …, Sn, tn, dn)
    if S1>= t1 and … and Sn>= tn then
    for i:=1 to n do
    Si:= Si - di ;
    endfor
    else

    endif

    Ssignal(S1, d1, …, Sn, dn)
    for i:=1 to n do
    Si:= Si +di ;
    ….
    endfor

    只有一个信号量S的几种特殊情况:

    • Swait(S, d, d),,允许每次申请d个资源,若现有资源数少于d,不予分配。
      *Swait(S, 1, 1),蜕化为一般的记录型信号量,一次申请一个,至多分配一个(S>1时可计数,或S=1时可控制互斥)。
      *Swait(S, 1, 0),当S>=1时,允许多个进程进入某特定区,当S变为0后,阻止任何进程进入特定区,相当于可控开关。并不对S资源的数量产生影响。

    *信号量题目做题一般方法:

    1.分析问题,找出同步、互斥关系
    2.根据资源设置信号量变量
    3.写出代码过程,并注意P、V操作的位置
    4.检查代码,模拟机器运行,体验信号量的变化和程序运行过程是否正确。

    展开全文
  • 什么信号量 信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。 信号量的值正的时候,说明它空闲。所测试的线程可以锁定而使用它。若为0,说明它被占用,测试的线程要进入...
  • 操作系统之信号量

    万次阅读 多人点赞 2018-03-29 23:13:32
    操作系统中的信号量在解决线程之间的同步中起着非常大的作用,那么什么信号量呢?百度百科:信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发...
  • UCOSIII信号量,互斥信号量

    千次阅读 2016-04-13 21:05:44
    UCOSIII信号量信号量:二值信号量(共享资源)  计数信号量(任务同步)·  任务内带信号量(只能用于任务同步,一种计数信号量) 1:二值信号量,计数信号量 //定义信号量 OS_SEM MY_SEM; //创建信号量 ...
  • 信号量机构是一种功能较强的机制,可用来解决互斥与同步的问题,它只能被两个标准的原语wait(S)和signal(S)来访问,也可以记“P操作”和“V操作”。原语是指完成某种功能且不被分割不被中断执行的操作序列,通常...
  • FreeRTOS 信号量

    千次阅读 2016-10-27 17:17:09
    二进制信号量 二进制信号量使用 二进制信号量实现 创建信号量 获取信号量 释放信号量 中断中释放 任务中释放 计数信号量 互斥锁 创建互斥信号量 拿锁 放锁 递归互斥锁 获取递归信号量 释放递归信号量 参考 ...
  • ios-GCD信号量

    2017-11-23 20:44:50
    信号通知时,信号量会+1,等待时,如果信号量大于0,则会将信号量-1,否则,会等待直到信号量大于0什么时候会大于零呢?往往是在之前某个操作结束后,我们发出信号通知,让信号量+1。 说完概念,我们来看看...
  • 信号量semaphore解析

    千次阅读 2014-10-23 10:46:00
    信号量在创建时需要设置一个初始值,表示同时可以有几个任务可以访问该信号量保护的共享资源,初始值1就变成互斥锁(Mutex),即同时只能有一个任务可以访问信号量保护的共享资源。 一个任务要想访问共享资源,...
  • System V信号量 与 Posix信号量的区别

    千次阅读 多人点赞 2020-03-21 19:26:44
    信号量是什么 信号量是一种计数器,用来控制对多个进程/线程共享的资源进行访问。...为什么信号量分两套(两套有什么区别) 简要的说,Posix是“可移植操作系统接口(Portable Operating System Interface...
  • FreeRTOS计数信号量使用

    千次阅读 2020-02-18 09:41:54
    基本特性 计数信号量,也可以看成是队列,但是长度大于1。...信号量计数值初始为0。 (2)资源管理 用于指示可用的资源。 当信号好计数值到0的时候,表示没有资源可用。 一个任务想要使用...
  • 事件之信号量

    千次阅读 2016-02-28 20:37:46
    1.什么信号量 信号量是事件的一种,使用信号量的最初目的,是为了给共享资源建立一个标志,该标志表示该共享资源的占用情况。这样,当一个任务在访问共享资源之前,就可以现对这个标志进行查询,从而在了解资源被...
  • Linux信号量详解

    万次阅读 2018-05-02 13:29:02
    只允许对它进行两个操作:1)等待信号量当信号量值为0时,程序等待;当信号量值大于0时,信号量减1,程序继续运行。2)发送信号量信号量值加1。我们使用信号量,来解决进程或线程间共享资源引发的同步问题。2.Linux...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 230,185
精华内容 92,074
关键字:

信号量为0表示什么