zoukankan      html  css  js  c++  java
  • IPC之信号量

    无名信号量

    POSIX标准提出了有名信号量和无名信号量来同步进程和线程,而linux(2.6以前)只实现了无名信号量。

    sem_overview中有详细介绍:man 7 sem_overview.

    System V semaphores(semget, segop, etc.)是旧的信号量API,但应用广泛。 posix信号量简单易用。

    命令行ipcs可提供ipc相关信息,如显示调用进程的信号灯,ipcs -s。

    • Posix Sem
    #include <semaphore.h>
    int sem_init(sem_t *sem, int pshared, unsigned int value);
    int sem_destroy(sem_t *sem);
    int sem_wait(sem_t *sem);
    int sem_trywait(sem_t *sem);
    int sem_post(sem_t *sem);
    int sem_getvalue(sem_t *sem);
    
    

    pshared决定了信号量是否在几个进程间共享,0信号量在线程间共享;非0表信号量在进程间共享.

    编译上面几个函数程序要加上-lrt选项,以连接the real-time library, librt.so库。

    加锁步骤:值大于0,值减1,锁成功;值小于等于0,则锁不成功阻塞。

    解锁步骤:值加1,唤醒所有阻塞线程。

    • System sem
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>
    key_t ftok(char *pathname, int proj);
    int semget(key_t key, int nsems, int semflg);
    int semctl(int semid, int semnum, int cmd, union semun arg);  // semnum指出感兴趣的特定信号灯。
    int semop(int semid, struct sembuf *spos, int nspos);  //nspos为spos指向的数组的元素个数
    
    
    struct sembuf{
        short sem_num; /*使用哪一个信号*/  
        short sem_op; /*进行什么操作*/
        short sem_flg; /*操作的标志*/    
    };

    sembuf结构中,sem_num是信号灯的编号,其值从0到nsems-1,sem_op是执行的操作,而sem_flg调整semop的行为。sem_op能够为正值、负值和0。
    >>如果sem_op为正,信号灯控制的资源被释放,而且信号灯的值增加。
    >>如果sem_op为负,调用进程表示它将等待直到受控资源被释放,此时信号灯的值减小而资源被调用进程加锁。
    >>如果sem_op为0,调用进程阻塞直到信号灯变为0;如果信号灯已经是0,调用立即返回。
    sem_flg可以为IPC_NOWAIT,不等待直接返回,或者SEM_UNDO,这意味着当调用semop的进程退出后执行的操作将被撤销。

    cmd可以取值:GETVAL,SETVAL,GETPID,GETNCNT(在信号灯上等待的进程数),GETZCNT(等待信号灯的值为0的进程数),GETALL,SETALL,
    IPC_RMID(删除带有semid的信号灯),IPC_SET(在信号灯上设置模式--权限位), IPC_STAT(每个信号灯都有一个数据结构semid_ds,
    这个数据结构完整地描述它的配置和行为。IPC_STAT把这些配置信息复制到semun结构的成员arg.buf中)

    创建信号量集
    The semget() system call returns the semaphore set identifier associated with the argument key. A new set of nsems semaphores is created
    if key has the value IPC_PRIVATE or if no existing semaphore set is associated with key and IPC_CREAT is specified in semflg.
    If  semflg  specifies both IPC_CREAT and IPC_EXCL and a semaphore set already exists for key, then semget() fails with errno set to EEXIST.  
    (This is analogous to the effect of the combi‐nation O_CREAT | O_EXCL for open(2).)
    假如指定参数key为IPC_PRIVATE,或与key相关的信号集不存在且semflg为IPC_CREAT,则信号集被创建。
    If successful, the return value will be the semaphore set identifier (a nonnegative integer), otherwise -1 is returned, with errno indicating the error.
    创建key
    ftok - convert a pathname and a project identifier to a System V IPC key
    The ftok() function uses the identity of the file named by the given pathname (which must refer to an existing, accessible file)
    and the least significant 8 bits of proj_id (which must be nonzero) to generate a key_t type System V IPC key, suitable for use with msgget(2), semget(2), or shmget(2).
    The resulting value is the same for all pathnames that name the same file, when the same value of proj_id is used.
    The value returned should be different when the (simultaneously existing)files or the project IDs differ.
    On success, the generated key_t value is returned. On failure -1 is returned, with errno indicatine the error as for the stat(2) system call.
    
    
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>
    
    int main(void)
    {
        int semid;
        int nsems = 1;
        int flags = 0666;
        struct sembuf buf;
    
        semid = semget(IPC_PRIVATE, nsems, flags);
        if(semid < 0)
        {   
            perror("semget");
            exit(EXIT_FAILURE);
        }   
        printf("semaphore created: %d
    ", semid);
    
        buf.sem_num = 0;
        buf.sem_op = 1;
        buf.sem_flg = IPC_NOWAIT;
    
        if((semop(semid, &buf, nsems)) < 0)
        {
            perror("semop");
            exit(EXIT_FAILURE);
        }
    
        system("ipcs -s");
        exit(EXIT_SUCCESS);
    }
    多次运行结果如下:
    ~$./a.out 
    semaphore created: 131076
    
    ------ Semaphore Arrays --------
    key        semid      owner      perms      nsems     
    0x00000000 0          yu       666        1         
    0x00000000 32769      yu       666        1         
    0x00000000 65538      yu       666        1         
    0x00000000 98307      yu       666        1         
    0x00000000 131076     yu       666        1 
    
    
    include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char **argv)
    {
        int semid;
    
        if(argc != 2)
        {   
            puts("USAGE: sctl <semaphore id>");
            exit(EXIT_FAILURE);
        }   
        semid = atoi(argv[1]);
    
        if((semctl(semid, 0, IPC_RMID)) < 0)
        {   
            perror("semctl IPC_RMID");
            exit(EXIT_FAILURE);
        } else {
            puts("semaphore removed");
            system("ipcs -s");
        }
    
        exit(EXIT_SUCCESS);
    }
    ~$./a.out 
    USAGE: sctl <semaphore id>
    ~$./a.out 0
    semaphore removed
    
    ------ Semaphore Arrays --------
    key        semid      owner      perms      nsems     
    0x00000000 32769      yu       666        1         
    0x00000000 65538      yu       666        1         
    0x00000000 98307      yu       666        1         
    0x00000000 131076     yu       666        1  
    主要应用于保护临界资源(同一时刻只有一个进程可以访问资源)。
  • 相关阅读:
    【大数据】HDFS高可用
    【Redis】常用命令、问题排查、内存优化
    【OOM】记一次线上OOM解决全流程
    【Git】Github如何弥补提交记录contributions
    Hash算法与Hash碰撞
    【计算机基础】存储单位换算
    【大数据】技术选型对比
    【MQ】Kafka架构与原理
    【Git】Git常用命令合集
    【maven】基本知识点
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/5079824.html
Copyright © 2011-2022 走看看