您的位置:首页 > 运维架构 > Linux

Linux进程通信——信号量

2016-07-14 20:49 435 查看
/*
* 进程间通信之信号量,代码源自《Linux程序设计》
*/
#include <iostream>
#include <string>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
// 使用信号量必须包含该文件
#include <sys/sem.h>

using namespace std;

// 自定义的一个联合体,信号量相关函数需要使用
union semun
{
int val;
struct semid_ds* buf;
unsigned short* array;
};

// 初始化信号量
int set_semvalue(int semid)
{
union semun sem_union;
// 信号量的初始值是1
sem_union.val = 1;

// 使用semctl函数去设置它,参数为SETVAL
if(semctl(semid,0,SETVAL,sem_union) == -1)
{
cout << "set_semvalue failed!"<< endl;
return 0;
}
return 1;
}

// 删除一个信号量
int del_semvalue(int semid)
{
union semun sem_union;
// 使用semctl去删除它,标志是IPC_RMID
if(semctl(semid,0,IPC_RMID,sem_union) == -1)
{
cout << "del_semvalue failed!"<< endl;
return 0;
}

return 1;
}

// 等待信号量
int semaphore_p(int semid)
{
struct sembuf sem_b;

sem_b.sem_num = 0;  // 如果不是使用一组信号,那么这个值一般都是0
sem_b.sem_op = -1;    // 表示进行P操作
sem_b.sem_flg = SEM_UNDO; // 默认都要设置为SEM_UNDO(这是为了,当进程异常退出的时候,系统可以释放进程持有的信号量)
// 调用semop进行P操作
if(semop(semid,&sem_b,1) == -1)
{
cout << "semaphore_p failed!"<< endl;
return 0;
}

return 1;
}

// V操作,释放信号量
int semaphore_v(int semid)
{
struct sembuf sem_b;

sem_b.sem_num = 0;
sem_b.sem_op = 1;   // 1表示进行V操作
sem_b.sem_flg = SEM_UNDO;

if(semop(semid,&sem_b,1) == -1)
{
cout << "semaphore_v failed!"<< endl;
return 0;
}
return 1;
}

int main(int argc,char* argv[])
{
// 信号量的id
int sem_id;

char op_char = 'O';

// 创建或者打开一个信号量(信号量不存在就创建、存在就打开)
sem_id = semget((key_t)1234,1,0666|IPC_CREAT);

// 用一个额外的参数去控制哪个进程对信号量进行初始化,即如果当前进程有额外的参数
// 那么它就对信号量进行初始化
if(argc > 1)
{
// 初始化信号量
if(set_semvalue(sem_id) == 0)
{
return -1;
}

op_char = 'X';
sleep(2);
}

for(int i = 0; i < 10; ++i)
{
// 等待信号量
if(semaphore_p(sem_id) == 0)
{
return -1;
}

// 打印一些信息
cout << op_char ;
cout.flush();
sleep(2);
cout << op_char;
cout.flush();

// 释放信号量,即V操作
if(semaphore_v(sem_id) == 0)
{
return -1;
}

sleep(2);
}

// 执行结束,打印一些信息
cout << endl << getpid() << " - finished" << endl;

// 用额外的参数去控制进程去删除信号量
if(argc > 1)
{
if(del_semvalue(sem_id) == 0)
{
return -1;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: