多进程——System V信号量

概述

lLinux 操作系统中有两种信号量分别为System V和Posix 。其中Posix 信号量可以用于多线程和多进程同步,但是Posix 信号量一般只有0和1两个值。但是system V信号量可以的数值范围可以变化一般默认的范围为0~2^15 - 1,同时对于system V信号量来说其申请的不是以个来申请而是以组的概念进行申请。

使用

创建system V信号量

system V信号量使用semget函数进行申请。semget函数在成功申请到信号量之后,会返回一个信号量的标记值,用于之后对信号量的控制和访问。
该函数调用如下:

int semget(key_t key, int nsems, int semflg);

其中key为键值需要具有唯一性,如果这个值相同那么对应的信号量相同。该值一般由ftok函数产生,ftok函数负责产生一个在系统中具有唯一性的值。ftok函数如下:

key_t ftok(const char *pathname, int proj_id);

其中的pathname需要为一个文件路径,该路径必须是具体存在的,因为ftok在生成key值时需要使用到文件的inode值,因为inode值在文件系统中具有唯一性。第二个参数proj_id为偏移值,这个值的末尾8位也同时参与到key的计算中,防止通过inode值进行生成时由于文件相同出现重复。
semget的第二个参数为nsem,即所需申请的system V信号量组中信号量的数目。
第三个参数semflg负责指定这个system V信号量的的读写权限,该权限和system V的作用范围相关,如果希望信号量的适用范围尽可能广,那么可以设置为0666。

对system V信号量赋初值

赋初值需要调用如下函数

semctl(data_req_p_id, 0, SETVAL, sem_union);
需要注意的是上面赋初值的使用方式是semctl较为简单的使用方式,semctl本质上有很多调用方式。

  • 其中data_rep_p_id是信号量的标记值。
  • 第二个参数0指明操作信号量组中的第几个信号量,(system V信号量以组的方式进行分配)
  • 第三个参数SETVAL是对应的命令,该参数指明semctl函数应该进行的操作为赋值操作
  • 第四个参数sem_union是一个联合体,负责传递具体的初值
    定义如下:
union semun {
        int val;                        /* value for SETVAL */
        struct semid_ds *buf;                /* buffer for IPC_STAT, IPC_SET */
        unsigned short int *array;         /* array for GETALL, SETALL */
        struct seminfo *__buf;                /* buffer for IPC_INFO */
};

生成system V信号量之后,需要对system V信号量赋予初值。需要注意的时,对于system V信号量来说,其创建和赋初值是分开的,这将导致一个system V信号量在赋值时可能会出现多个进程同时赋值导致初值不确定的情况,不过这一点可以通过下面的代码进行避免:

    if (0 <= (data_req_p_id = semget(data_qp_id, 1, oflag)))
    {
        sem_union.val = 0;
        semctl(data_req_p_id, 0, SETVAL, sem_union);
    }
    else if (errno == EEXIST)
    {
        data_req_p_id = semget(data_qp_id, 1, SVSEM_MODE);
    }
    else
    {
        perror("data_req_p_id semget error\n");
    }

不过上面的方式只是简单的适用于不对等的进程之间(一个进程为信号量的中心持有进程开始就被创建,其他进程在之后被陆续创建)。另外一个更好的方法时通过信号量中的一个属性值sem_otime来进行同步。这个方法的原理在于sem_otime在信号量创建时被置为0,只有在调用sem_op函数后才会变为非零值。
因此只要在上面的data_req_p_id = semget(data_qp_id, 1, SVSEM_MODE);后面使用IPC_STAT命令调用semctl函数,等待sem_otime 变为非0时即可。这个方法可以更加有效地防止出现system V信号量初值不确定的情况发生。

sytem信号量操作

对信号量的操作函数为semop,函数申明如下所示:

int semop(int semid, struct sembuf *sops, size_t nsops);

  • 第一个参数semid为信号量的标记值
  • 第二个参数sembuf如下所示:
struct sembuf
{
  unsigned short int sem_num;   /* semaphore number */
  short int sem_op;     /* semaphore operation */
  short int sem_flg;        /* operation flag */
};

其中sem_num指的不是数目,而是system V信号量组中序列号(本质上就是几个和第几个的区别)。sem_op指的是对信号量的操作值。sem_flg指对信号量的操作的flag。这个flag总共有三种情况:

  • 第一种为不指定,默认状态为阻塞状态
  • 第二种IPC_NOWAIT,设置为不阻塞状态,
  • 第三种为SEM_UNDO,这一种需要特殊说明,SEM_UNDO并不是指不做任何事情,该值的实际意义为将每一次的操作值都加入到一个中间变量semadj中,具体如下所示:

sem_op < 0 : semadj = semadj + sem_op的绝对值
sem_op > 0 : semadj = semadj - sem_op的绝对值

当某一个调用该信号量的进程退出时,semadj的值会加到当前信号量的值semval上。所以SEM_UNDO的真正意义为“复旧”。当定义了该属性的进程退出时,该进程对信号量的操作会变得和原始没有允许改进程时相同。因此当信号量用来作为同步信号量即一个进程负责P操作,另外一个进程负责V操作时,不能指定该属性,因为单独一个进程对该信号量的操作都是独立的P或者V,这会导致单独一个进程中的semadj中间变量的值一直+1或者-1,最后出现semadj越界的情况,导致信号量同步失败。

  • 第三个参数为nsops指明sembuf的数目(即对system V信号量组还总多少个信号量进行操作)。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容