zoukankan      html  css  js  c++  java
  • linux Posix 信号量 二

    一、Posix信号量

     

    1.Posix信号量分为两种:

    1.   有名信号量:使用Posix IPC名字标识(有名信号量总是既可用于线程间的同步,又可以用于进程间的同步)

    2.   内存信号量:存放在共享内存区中(基于内存的信号量则必须在创建时指定成是否在进程间共享,且在所有进程的共享内存区,具有随进程的持续性)

    Posix信号量不必在内核中维护(System V信号量由内核维护),由可能为路径名的名字来标识。

    (Posix信号量更常用于进程间同步,互斥锁常用于线程间同步)

     

    2.基本操作:

    1.   创建(create):指定初始值。

    2.   等待(wait):如果值小于等于0则阻塞,否则将其减一,又称P操作。

    3.   挂出(post):将信号量的值加1,加后如果值大于0,则唤醒一个阻塞在等待上的线程,又称V操作。

    二值信号量可用于互斥,就像互斥锁一样。但互斥锁必须由锁住它的线程解锁,信号量的挂出却不必由执行过等待的同一线程执行。

    信号量的wait和post与条件变量的wait和signal类似,区别是:因为永久的改变了信号量的值,信号量的操作总被记住(会影响到后续的操作);条件变量的signal如果没有线程在等待,该信号将丢失(对后续操作没有影响)。

    互斥锁是为上锁而优化的,条件变量是为等待优化的,信号量既可以上锁也可以等待,因此开销更大。

    3.Posix信号量操作

    有名信号量:

    内存信号量:

    sem_open

    sem_init:需要指定是否共享

                                                                     sem_wait:原子的“测试并减1”操作

                                                                     sem_trywait

                                                                     sem_post:同步技巧中唯一能在信号处理函数内安全调用的操作

                                                                     sem_getvalue

    sem_close

    sem_destroy

    sem_unlink

     

    即使当前没有进程打开信号量,它的值仍然保持,因此Posix有名信号量至少是随内核持续的。

    在父进程中打开的任何信号量,fork后在子进程中仍打开。

     

     

     

    关于posix有名信号量使用的几点注意

     

    1、有名信号量使用sem_unlink从系统中删除。每个信号量有一个引用计数器记录当前的打开次数,sem_unlink必须等待这个数为0时才能把name所指的信号量从文件系统中删除。也就是要等待最后一个sem_close发生。

     

    2、彼此无亲缘关系的进程间需使用信号量时,一般用有名信号量。如果不需要使用关联名字时,可改用内存信号量。

    内存信号量需要放在共享内存区中,并由sem_init函数初始化为shared状态才能被不同进程使用,这种情况下它的持续性与共享内存区相同。sem_init总是初始化信号量的值,因此,对于一个给定的信号量,必须小心保证只调用sem_init一次。

     

    3、我们可以用sem_wait来申请共享资源,sem_wait函数可以测试所指定信号量的值,如果该值大于0,那就将它减1并立即返回。我们就可以使用申请来的共享资源了。如果该值等于0,调用线程就被进入睡眠状态,直到该值变为大于0,这时再将它减1,函数随后返回。sem_wait操作必须是原子的。sem_wait和sem_trywait的差别是:当所指定信号量的值已经是0时,后者并不将调用线程投入睡眠。相反,它返回一个EAGAIN错误。

     当一个线程使用完某个信号量时,它应该调用sem_post来告诉系统申请的资源已经用完。本函数和sem_wait函数的功能正好相反,它把所指定的信号量的值加1,然后唤醒正在等待该信号量值变为正数的任意线程。

     

    4、.Posix有名信号量的值是随内核持续的。也就是说,一个进程创建了一个信号量,这个进程结束后,这个信号量还存在,并且信号量的值也不会改变。

     

    5、当持有某个信号量锁的进程没有释放它就终止时,内核并不给该信号量解锁。

     

     

    posix有名信号量应用于多线程

    #include <semaphore.h>

    #include <unistd.h>

    #include <stdio.h>

    #include <fcntl.h>

    #include <thread.h>

     

    void *thread_function(void *arg); /*线程入口函数*/

    void print(pid_t); /*共享资源函数*/

    sem_t *sem; /*定义Posix有名信号量*/

    int val; /*定义信号量当前值*/

     

    int main(int argc,char *argv[])

    {

    int n=0;

     

    if(argc!=2)

    {

        printf(“please input a file name! ”);

        exit(1);

    }

    sem=sem_open(argv[1],O_CREAT,0644,3); /*打开一个信号量*/

     

    while(n++<5) /*循环创建5个子线程,使它们同步运行*/

    {

        if((pthread_create(&a_thread,NULL,thread_function,NULL))!=0)

            {

                 perror(“Thread creation failed”);

                 exit(1);

             }

    }

    pthread_join(a_thread,NULL);

    sem_close(bin_sem);

    sem_unlink(argv[1]);

    }

     

    void *thread_function(void *arg)

    {

    sem_wait(sem); /*申请信号量*/

        print(); /*调用共享代码段*/

        sleep(1);

        sem_post(sem); /*释放信号量*/

        printf(“I’m finished,my tid is %d ”,pthread_self());

    }

     

    void print()

    {

    printf(“I get it,my tid is %d ”,pthread_self());

    sem_getvalue(sem,&val);

    printf(“Now the value have %d ”,val);

    }

     

    程序用循环的方法建立5个线程,然后让它们调用同一个线程处理函数thread_function,在函数里我们利用信号量来限制访问共享资源的线程数。共享资源我们用print函数来代表,在真正编程中它有可以是一个终端设备(如打印机)或是一段有实际意义的代码。

  • 相关阅读:
    json数据转为对象,一般在前台把数据传回后端中使用 转https://www.cnblogs.com/zxtceq/p/6610214.html
    JavaScript事件大全3
    javascript大全
    Javascript刷新页面大全
    JavaScript验证正则表达式大全
    insertAdjacentHTML和insertAdjacentText方法
    CSS实现样式布局
    iis浏览网页时提示无法显示 XML 页
    IIS浏览提示无法显示网页的解决方法
    在dreamweaver中输入代码时不会有提示的解决办法
  • 原文地址:https://www.cnblogs.com/jiangzhaowei/p/4203047.html
Copyright © 2011-2022 走看看