linux进程间传值,Linux 下进程间通信机制(六) 信号灯集 Semaphore Arrays
发布日期:2021-06-27 04:24:38 浏览次数:1 分类:技术文章

本文共 3762 字,大约阅读时间需要 12 分钟。

信号灯集函数定义如下:

#include

int semctl(int sem_id, int sem_num, int command, ...);

int semget(key_t key, int num_sems, int sem_flags);

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

semget函数创建一个新的信号量或是获得一个已存在的信号量键值。

semop函数用来改变信号量的值(包含P操作和V操作)。

semctl函数允许信号量信息的直接控制(包含初始化信号灯和删除信号灯)。

事实上,为了获得我们特定操作所需要的#define定义,我们需要在包含sys/sem.h文件之前通常需要包含sys/types.h与sys/ipc.h文件。

相关的类型定义:

struct  sembuf{

unsigned short sem_num;  /* semaphore number *//*信号灯在信号灯集中的编号*/

short          sem_op;   /* semaphore operation *//*P操作或者V操作*/

short          sem_flg;  /* operation flags */

};

//这个联合体需要在程序声明,用于semctl函数的SETVAL选项的传值,作为第四个参数。

union semun {

int val;

struct semid_ds *buf;

unsigned short *array;

}

demo

进程间利用共享内存机制通信,一个进程写,一个进程读,用信号灯同步。

//writer.c

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define R 0

#define W 1

#define N 1024

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;

};

void pv(int semid, int op, int num)

{

struct sembuf buf;

buf.sem_num = num;//信号灯编号

buf.sem_op = op; //p操作或者v操作

buf.sem_flg = 0;

/*semid为信号灯集id, buf为struct sembuf结构体指针, 1表示操作信号灯的个数为1,如果大于一,表示操纵多个(则buf为struct sembuf结构体的数组指针)*/

if (semop(semid, &buf, 1) == -1)

{

perror("semop");

exit(-1);

}

}

int main()

{

int semid, shmid;

key_t key;

char *shmaddr;

if ((key = ftok(".", 'a')) == -1)

{

perror("ftok");

exit(-1);

}

//先启动的进程负责进行初始化,信号灯集中由两个信号灯,一个为读,一个为写

if ((semid = semget(key, 2, 0666 | IPC_CREAT | IPC_EXCL)) == -1)

{

if (errno == EEXIST)

{

semid = semget(key, 2, 0666);

}

}

else //first

{

union semun un;

un.val = 0;

//读的信号灯值为0

if (semctl(semid, R, SETVAL, un) == -1)

{

perror("init R");

exit(-1);

}

//写的信号灯值为1

un.val = 1;

if (semctl(semid, W, SETVAL, un) == -1)

{

perror("init R");

exit(-1);

}

}

//创建共享内存

if ((shmid = shmget(key, N, 0666 | IPC_CREAT)) == -1)

{

perror("shmget");

exit(-1);

}

//映射共享内存

if ((shmaddr = (char *)shmat(shmid, NULL, 0)) == (char *)-1)

{

perror("shmaddr");

exit(-1);

}

while (1)

{

//p(w) fgets v(r)

pv(semid, -1, W);

fgets(shmaddr, N, stdin);

pv(semid, 1, R);

if (strncmp(shmaddr, "quit", 4) == 0)

break;

}

usleep(100000);

if(semctl(semid, 0, IPC_RMID) == -1)

{

perror("rm sem");

exit(-1);

}

if (shmdt(shmaddr) == -1)

{

perror("shmdt");

exit(-1);

}

if (shmctl(shmid, IPC_RMID, NULL) == -1)

{

perror("shmctl");

exit(-1);

}

exit(0);

}

//reader.c

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define R 0

#define W 1

#define N 1024

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;

};

void pv(int semid, int op, int num)

{

struct sembuf buf;

buf.sem_num = num;

buf.sem_op = op;

buf.sem_flg = 0;

if (semop(semid, &buf, 1) == -1)

{

perror("semop");

exit(-1);

}

}

int main()

{

int semid, shmid;

key_t key;

char *shmaddr;

if ((key = ftok(".", 'a')) == -1)

{

perror("ftok");

exit(-1);

}

if ((semid = semget(key, 2, 0666 | IPC_CREAT | IPC_EXCL)) == -1)

{

if (errno == EEXIST)

{

semid = semget(key, 2, 0666);

}

}

else //first

{

union semun un;

un.val = 0;

if (semctl(semid, R, SETVAL, un) == -1)

{

perror("init R");

exit(-1);

}

un.val = 1;

if (semctl(semid, W, SETVAL, un) == -1)

{

perror("init R");

exit(-1);

}

}

if ((shmid = shmget(key, N, 0666 | IPC_CREAT)) == -1)

{

perror("shmget");

exit(-1);

}

if ((shmaddr = (char *)shmat(shmid, NULL, 0)) == (char *)-1)

{

perror("shmaddr");

exit(-1);

}

srandom(getpid());

while (1)

{

//p(r) printf v(w)

pv(semid, -1, R);

printf("%s", shmaddr);

if (strncmp(shmaddr, "quit", 4) == 0)

{

//v(r)

pv(semid, 1, R);

break;

}

pv(semid, 1, W);

sleep(random()%5+1);

}

if (shmdt(shmaddr) == -1)

{

perror("shmdt");

exit(-1);

}

exit(0);

}

转载地址:https://blog.csdn.net/weixin_42166105/article/details/116678342 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Linux登录远程机脚本,Linux中使用expect脚本实现远程机器自动登录
下一篇:手机 运行linux程序,linux deploy官网手机是可以仿真运行x86linux

发表评论

最新留言

初次前来,多多关照!
[***.172.111.71]2022年05月22日 09时16分03秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

最新文章