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

Linux程序设计笔记--IPC操作--semaphores

2012-04-08 18:11 197 查看
IPC操作就是通常说的进程间通信(interProcessCommunication,进程间通信)。IPC操作有三种:信号量,共享内存,消息队列。
1.信号量。
信号量的作用是保证共享资源有效访问。
信号量有关函数:
int semget(key_tkey,int num_sems,int sem_flags);获取或者创建键值key对应的信号量,返回值信号量标识符。
key_t信号量键值,可以随意取。特殊键值IPC_PRIVATE,创建只能有本进程使用的信号量。
num_sems信号量的个数,一般取1。
sem_flags信号量的访问权限,与open中的权限相似,与IPC_CREAT或操作,如果不存在创建信号量,如果存在忽略IPC_CREAT关键字,直接获取信号量标识符。
int semop(intsem_id,struct sembuf *sem_ops,size_t num_sem_ops); //信号量PV操作。
struct sembuf
{
short sem_num;//信号量的编号,工作方式不需要一组信号量,这个值为0;
short sem_op; //对信号量PV操作时,加减的数值,可以为+1,-1,或其他。
short sam_flg;//通常设置为SEM_UNDO。作用是:程序在没有释放信号量的情况下结束时,系统自动释放该信号量。
};
sem_id信号量标识符。sembuf信号量操作数值。num_sem_ops通常设置为1.
int semctl(intsem_id,int sem_num,int command,...); //对信号量的管理具体操作。
sem_id信号量标识符,sem_num信号量的标号。command采取的动作。如果有第四个参数,将会是一个unionsemun复合结构。只要包括以下成员:
union semun{
int val;
struct semid_ds*buf;
unsigned short*arry;
}
一般常用的command操作有两个:
SET_VAL:用来把信号量初始化为一个已知的值。这个值有unionsemun结构离得val值传递。
IPC_RMID:删除一个已经没人继续使用的信号量标识码。
semctl函数根据不同的command命令返回不同的值,SET_VAL,IPC_RMID操作成功返回0,失败返回-1。

Semarphore

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

#include <sys/sem.h>

#include "semun.h"

union semun {
int val; /* value for SETVAL */

structsemid_ds *buf; /* buffer for IPC_STAT, IPC_SET */

unsignedshort int *array; /* array for GETALL, SETALL */

structseminfo *__buf; /* buffer for IPC_INFO */

};

static intset_semvalue(void);
static voiddel_semvalue(void);
static intsemaphore_p(void);
static intsemaphore_v(void);

static int sem_id;

int main(int argc,char *argv[])
{
int i;
int pause_time;
char op_char ='O';

srand((unsignedint)getpid());

sem_id =semget((key_t)1234, 1, 0666 | IPC_CREAT);

if (argc > 1){
if(!set_semvalue()) {
fprintf(stderr, "Failed to initialize semaphore\n");

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

for(i = 0; i <10; i++) {

if(!semaphore_p()) exit(EXIT_FAILURE);

printf("%c",op_char);fflush(stdout);

pause_time =rand() % 3;
sleep(pause_time);
printf("%c",op_char);fflush(stdout);

if(!semaphore_v()) exit(EXIT_FAILURE);

pause_time =rand() % 2;
sleep(pause_time);
}

printf("\n%d- finished\n", getpid());

if (argc > 1){
sleep(10);
del_semvalue();
}

exit(EXIT_SUCCESS);
}

static intset_semvalue(void)
{
union semunsem_union;

sem_union.val =1;
if(semctl(sem_id, 0, SETVAL, sem_union) == -1) return(0);

return(1);
}

static voiddel_semvalue(void)
{
union semunsem_union;

if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1)

fprintf(stderr, "Failed to delete semaphore\n");

}

static intsemaphore_p(void)
{
struct sembufsem_b;

sem_b.sem_num =0;
sem_b.sem_op =-1; /* P() */
sem_b.sem_flg =SEM_UNDO;
if(semop(sem_id, &sem_b, 1) == -1) {

fprintf(stderr, "semaphore_p failed\n");

return(0);
}
return(1);
}

static intsemaphore_v(void)
{
struct sembufsem_b;

sem_b.sem_num =0;
sem_b.sem_op =1; /* V() */
sem_b.sem_flg =SEM_UNDO;
if(semop(sem_id, &sem_b, 1) == -1) {

fprintf(stderr, "semaphore_v failed\n");

return(0);
}
return(1);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: