嵌入式Linux热门培训内容之Linux信号量

时间:2018-12-13 17:33:33

问:什么是信号量?

答:信号量是一个特殊的整数,最大值是32767

问:为什么需要信号量?

答:信号量是用来解决线程间同步或互斥的一种机制

举个栗子:

我们把信号量举栗为一个厕所,假设厕所有4个坑,有10个人想上大号,那么有6个人就需要在外面等待。

假设就只有一个坑,有两个人想上厕所,那就有一个人在外面等待,就变成了0,1信号量,相当于互斥锁,我上厕所的时候,你就得等着,你上厕所的时候,我就得等着。

操作相关函数:

创建信号量:

  创建或者打开一个信号量,需要使用sem_open()函数,函数原形如下:

  sem_t sem_open(const char * name, int oflag, mode_t mode, unsigned int value)

  返回值sem_t 是一个结构,如果函数调用成功,则返回指向这个结构的指针,里面装着当前信号量的资源数。

  参数name,就是信号量的名字,两个不同的进程通过同一个名字来进行信号量的传递。

  参数oflag,当他是O_CREAT时,如果name给出的信号量不存在,那么创建,此时必须给出mode和vaule。

  参数mode,指出信号量名字的权限

  参数vaule,信号量的初始值

关闭信号量:

  关闭有名信号量 sem_close(sem_t *sem)

  这个函数只有一个参数,意义也非常明显,就是指信号量的名字。

信号量操作:

  P操作:使用的函数是sem_wait(sem_t *sem)

  如果信号量的值大于零,sem_wait函数将信号量减一,并且立即返回。如果信号量的值小于零,那么该进程会被阻塞在原地。

  V操作:使用的函数是sem_post(sem_t *sem)

  当一个进程使用完某个信号量时,他应该调用sem_post函数来告诉系统收回资源。

  sem_post函数和sem_wait函数的功能刚好相反,他会把指定的信号量加一

删除有名信号量:

  当使用完有名信号后,需要调用函数sem_unlink来释放资源。

  函数原形:int sem_unlink(const char *name)

代码例子:

进程1

#include <stdio.h>

#include <stdlib.h>

#include <semaphore.h>

#include <errno.h>

#include <sys/stat.h>

#include <fcntl.h>

int main()

{

    sem_t *sem_test;

    sem_test = sem_open("sem_test_01", O_CREAT, 0644, 0); 

    if(sem_test < 0)

    {   

          printf("create sem error errno=%d\n",errno);

          exit(-1);

    }   

    printf("process TMAC set to waiting……\n");

    printf("This is 1\n");

    sem_wait(sem_test);

    printf("This is 3\n");

    sem_post(sem_test);

    printf("process TMAC GO OVER \n");

    sem_close(sem_test);

    sem_unlink("sem_test_01");

    return 0;

}

进程2、

#include<stdio.h>

#include<stdlib.h>

#include<semaphore.h>

#include<errno.h>

#include<sys/stat.h>

#include<fcntl.h>

int main()

{

    sem_t *sem_test;

    sem_test = sem_open("sem_test_01",0);

    if(sem_test < 0)

    {

        printf("process Paul creat sem error errno=%d\n",errno);

        exit(-1);

    }

    printf("process Paul 2\n");

    sem_post(sem_test);

    printf("process Paul GO OVER!\n");

    sem_close(sem_test);

    sem_unlink("sem_test_01");

    return 0;

}