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

linux进程通信--信号量

2016-05-31 20:33 405 查看
信号量的功能

信号量自身并不具有通信功能,而是在当多个进程访问同一资源时,使用信号量实现多个进程之间的互斥与同步,因此信号量相当于数据锁功能。简单的说信号量就是解决不同进程访问共享资源时,避免出现问题而产生的一种机制。

信号量是一个特殊的变量,程序对其访问都是原子操作,且只允许对它进行等待P(-1)操作和发送V(+1)操作。最简单的信号量是只能取0和1的变量,这也是信号量最常见的一种形式,叫做二进制信号量,而可以取多个正整数的信号量被称为通用信号量。

信号量的实现过程

信号量的实现过程:当进程获得信号量时,执行P(-1)操作,进入临界区,此时阻止其它进程对资源的访问,当该进程执行完毕,实行V(+1)操作,离开临界区。其他进程此时可以访问资源。

信号量操作函数

int semop(int semid, struct sembuf *sops, unsigned nsops);
//操作一组信号,实现PV操作
int semget(key_t key, int nsems, int semflg);
//nsems表示信号量的数量,通常设为1
//该函数实现当存在信号量时获取信号量,若不存在则创建信号量
//semflag表示创建信号量的标志位,设置为IPC_CREAT与权限标志位或,该方式可以实现不存在时,创建新的信号量,已存在时也不会报错
int semctl(int semid, int semnum, int cmd, ...);
对信号量进行初始化和删除信号量,
union semun {
int              val;    /* Value for SETVAL
struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET
unsigned short  *array;  /* Array for GETALL, SETALL
struct seminfo  *__buf;  /* Buffer for IPC_INFO
(Linux-specific)
};

unsigned short sem_num;  /* semaphore number
short          sem_op;   /* semaphore operation
short          sem_flg;  /* operation flags


4.应用实例

使用两个进程实现对终端进行输出,使用信号量实现两个进程之间的协调操作。

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <unistd.h>
int sem_id;
//定义共用体
union semun {
int val;               // SETVAL使用的值
struct semid_ds *buf;  // IPC_STAT、IPC_SET 使用缓存区
unsigned short *array; // GETALL,、SETALL 使用的数组
struct seminfo *__buf; // IPC_INFO(Linux特有) 使用缓存区
};
//声明函数
int sem_init();
int sem_del();
int semop_p();
int semop_v();

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

char message='W';   // 初始化输入参数
int sed_num;
sem_id=semget((key_t)1234, 1, 0666|IPC_CREAT);
//如果输入的参数大于1 则输出的参数为输入的值   否则的话 输出为X;
//如果输入的参数大于1  需要对信号量进行初始话   否则的话信号量不起作用
if(argc>1)
{
//程序第一次被调用
if(!sem_init())
{
printf("init semaphore failed\n");
}
message=argv[1][0];//输出参数
sleep(2);
}
//做10个循环    看两个程序同时共用 终端输出是否打架/冲突
for(sed_num=0;sed_num<10;sed_num++)
{

if(!semop_p())   //挂起信号量
exit(EXIT_FAILURE);
printf("The %d ,times send %c,current pid is %d\n",sed_num,message,getpid());
fflush(stdout);
sleep(rand()%3);//休眠一会
printf("The %d ,times send %c,current pid is %d\n",sed_num,message,getpid());
fflush(stdout);
sleep(rand()%3);
if(!semop_v())  //打印完毕
exit(EXIT_FAILURE);
sleep(1);
}
printf("The process %d is sucess\n",getpid());
sleep(5);
if(argc>1)
{
if(!sem_del())
{
exit(EXIT_FAILURE);
}
}

exit(0);
}
int sem_init()
{
union semun sem_num;
sem_num.val=1;
if(semctl(sem_id,0,SETVAL,sem_num)==-1)
{
//exit(EXIT_FAILURE);
return 0;
}
return 1;
}

int sem_del()
{
if(semctl(sem_id,0,IPC_RMID)==-1)
return 0;
else
return 1;
}
int semop_p()
{
struct sembuf semopler_p;

semopler_p.sem_num=0;  //对第sem_num  信号量进行操作     这里只有一个信号量所以只用0
semopler_p.sem_op=-1;
semopler_p.sem_flg=SEM_UNDO;
if(semop(sem_id,&semopler_p,1)==-1)   //第三个参数指的是信号量的个数
{
return 0;

}
else
return 1;
}
int semop_v()
{
struct sembuf semopler_v;

semopler_v.sem_num=0;  //对第sem_num  信号量进行操作     这里只有一个信号量所以只用0
semopler_v.sem_op=1;
semopler_v.sem_flg=SEM_UNDO;

if(semop(sem_id,&semopler_v,1)==-1)   //第三个参数指的是信号量的个数
{
return 0;

}
else
return 1;

}


5.总结

信号量是一种特殊变量,目的就是为了实现多个进程访问同一资源时出现冲突等现象的协调操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: