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);
}