信号量和共享内存的配合使用
来源:互联网 发布:青蛙城 知乎 编辑:程序博客网 时间:2024/05/22 05:17
信号量
信号量是一个计数器,常用于处理进程或线程的同步问题,特别是对临界资源访问的同步。
信号量的值大于或等于0时表示可供并发进程使用的资源实体数;小于0时代表正在等待使用临界资源的进程数
1、信号集的创建或打开
int semget(key_t key, int sems, int sem_flags);
key 是由ftok()的到的键值。 nsems指明要创建的信号集包含的信号个数,改参数后面还会提到。semflg为操作标志
- IPC_CREATE:调用semget()时,会将本信号集中的key值和其他信号集中的key进行对比,如果存在相同的key,说明信号集已存在,此时返回该信号集的标识符,否则新建一个信号集并返回其标识符。
- IPC_EXCL:该宏和IPC_CREATE一起使用,否则没有意义。当 semflg取PC_CREATE|IPC_EXCL时,表示如果发现信号集已经存在,则返回错误,错误码
为EEXIST。
2、信号量的操作
int semop(int semid, struct sembuf *sops, size_t nsops);
semid为信号集的标识符;sops指向进行操作的结构体首地址;nsops指出将要进行操作的信号个数。semop函数调用成功返回0,失败返回-1。
struct sembuf{ short sem_num;//信号在信号集中的索引 short sem_op;//信号量在一次操作中需要改变的数据,通常是两个数,一个是-1,即P(等待)操作, //一个是+1,即V(发送信号)操作。 short sem_flg;//操作标志IPC_NOWAIT,IPC_UNDO 详细请见UNIX高级环境编程};
信号集的控制
int semctl(int semid, int semnum, int cmd, ... /* union semun arg */);
semid为信号集的标识符;semnum标识一个特定的信号;cmd指明控制操作的类型;“…”说明函数的参数时可选的
union semun{ int val; /*for SETVAL*/ struct semid_ds *buf; /*for IPC_STAT and IPC_SET*/ unsigned short *array; /*for GETALL and SETALL*/};
cmd参数指定下列命令中的一种
共享内存
共享内存就是分配一块能被其他进程访问的内存。
共享内存区的创建
int shmget(key_t key, size_t size, int shmflg);
IPC_CREATE: 调用sheget时,系统将此值与其他所有共享内存区的key进行比较,如果存在相同的key,说明共享内存区已存在,此时返回该共享内存区的标识符,否则新建一个共享内存区并返回其标识符。
IPC_EXC: 该宏必须和IPC_CREATE 一起使用,否则没有意义。当shmflg取IPC_CREATE|IPC_EXCL时,表示如果发现信号集已经存在,则返回-1,错误码为EEXIST。
共享内存区的操作
在使用共享内存区前,必须通过shmat函数将其附加到进程的地址空间。进程与共享内存就建立了连接。
void* shmat(int shmid, const void* shmaddr, int shmflag);
shmid为shmget函数的返回值;参数shmflg为存取权限标志;参数shmaddr为共享内存的附加点,其不同取值说明如下:
进程结束使用共享内存后,要通过shmdt断开与共享内存区的连接。
int shmdt(const void* shmaddr);
参数shmaddr为shmat函数的返回值。调用成功返回0,否则返回-1。
共享内存区的控制
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
shmid为共享内存区的标识符;buf为指向shmid_ds结构体的指针;cmd为操作标志位
- IPC_RMID : 从系统中删除由shmid标识的共享内存区。
- IPC_SET : 设置共享内存区的shmid_ds结构。
- IPC_STAT : 读取共享内存区的shmid_ds结构,并将其存储到buf指向的地址中。
应用实例
ipc.h
#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<string.h>#include<sys/ipc.h>#include<sys/sem.h>#include<sys/shm.h>#include<sys/msg.h>#include<signal.h>union semun{ int val; struct semid_ds *buf; unsigned short *array; struct seminfo *__buf;};key_t Ftok(const char *pathname, int proj_id){ key_t key = ftok(pathname, proj_id); if(key == -1) { perror("ftok."); exit(1); } return key;}int Semget(key_t key, int nsems, int semflg){ int id = semget(key, nsems, semflg); if(id == -1) { perror("semget."); exit(1); } return id;}int Shmget(key_t key, size_t size, int shmflg){ int id = shmget(key, size, shmflg); if(id == -1) { perror("shmget."); exit(1); } return id;}void* Shmat(int shmid, const void *shmaddr, int shmflg){ void *addr = shmat(shmid, shmaddr, shmflg); if(addr == (void*)-1) { perror("shmat."); exit(1); } return addr;}int Msgget(key_t key, int msgflg){ int id = msgget(key, msgflg); if(id == -1) { perror("msgget."); exit(1); } return id;}
cli.c
#include"ipc.h"void cli_exit(int signo){ printf("Client exit. . .\n"); exit(0);}// ./cli . 0xffint main(int argc, char *argv[]){ struct sigaction act; act.sa_handler = cli_exit; key_t shm_key = Ftok(argv[1], atoi(argv[2])); int shm_id = Shmget(shm_key, 0, 0); char *addr = (char*)Shmat(shm_id, NULL, 0); int sem_id = Semget(shm_key, 0, 0); struct sembuf v = {1, 1, SEM_UNDO}; struct sembuf p = {0, -1, SEM_UNDO}; sigaction(SIGINT, &act, NULL); while(1) { semop(sem_id, &p, 1); printf("Ser:>%s\n",addr); printf("Cli:>"); scanf("%s",addr); semop(sem_id, &v, 1); } return 0;}
ser.c
#include"ipc.h"int shm_id, sem_id;char *addr;void ser_exit(int signo){ semctl(sem_id, 0, IPC_RMID); semctl(sem_id, 1, IPC_RMID); shmdt(addr); shmctl(shm_id, IPC_RMID, NULL); printf("Server exit . . .\n"); exit(0);}// ./ser . 0xffint main(int argc, char *argv[]){ struct sigaction act; act.sa_handler = ser_exit; key_t shm_key = Ftok(argv[1], atoi(argv[2])); shm_id = Shmget(shm_key, 1024, IPC_CREAT|IPC_EXCL|0755); addr = (char*)Shmat(shm_id, NULL, 0); sem_id = Semget(shm_key, 2, IPC_CREAT|IPC_EXCL|0755); union semun init; init.val = 0; semctl(sem_id, 0, SETVAL, init); semctl(sem_id, 1, SETVAL, init); struct sembuf v = {0, 1, SEM_UNDO}; //第一个参数代表0标志位,第二个是v操作后加的值 struct sembuf p = {1, -1, SEM_UNDO}; //第三个参数分为IPC_NOWAIT和SEM_UNDO sigaction(SIGINT, &act, NULL); while(1) { printf("Ser:>"); scanf("%s",addr); semop(sem_id, &v, 1); semop(sem_id, &p, 1); printf("Cli:>%s\n",addr); } return 0;}
运行示例
server端
client端
- 信号量和共享内存的配合使用
- 共享内存和信号量的使用
- 使用共享内存和信号量实现数据通信
- 共享内存和信号量
- 信号量和共享内存
- linux共享内存与信号量的使用
- 进程间通信(IPC)4 ------ 共享内存(配合使用信号量进行同步)
- 管道,信号量,共享内存,socket的实际使用场景和NSPipe管道的使用
- Linux信号量和共享内存
- 使用共享内存和信号量模仿cp命令
- 使用信号量和共享内存实现进程间通信
- system V 共享内存和信号量的组合使用 实现生产者消费者问题
- Linux进程同步与通讯:共享内存和信号量的使用
- Linux进程间通信的两种方式:使用共享内存和信号量
- linux 进程间共享内存与信号量的使用
- 进程间通信 "共享内存" 与 “信号量”的使用
- 使用信号量进行同步的共享内存机制
- 信号量和进程共享内存的小例子
- linux常用的系统监控top和sar
- Poi 导出
- SpannableString的setSpan报错java.lang.IndexOutOfBoundsException
- phpstorm 2017之输入法
- Java练习--异常(8)
- 信号量和共享内存的配合使用
- 238. Product of Array Except Self
- Python小程序,99乘法表,长方形,三级菜单,购物,邮件,百钱买百鸡
- UIDocumentInteractionController
- HDOJ 1391 Number Steps
- C语言之旅(1)指针
- openmpi 2.1.1 多网卡运行实例
- iOS编程基础-OC(三)-对象和消息传递
- 51nod 1389 跳跳树 倍增