标题:Linux进程通信-使用信号量
一、相关知识 信号量:一个整数; 大于或等于0时代表可供并发进程使用的资源实体数; 小于0时代表正在等待使用临界区的进程数; 用于互斥的信号量初始值应大于0; 只能通过P、V原语操作而改变; 信号量元素组成: 1、表示信号量元素的值; 2、最后操作信号量元素的进程ID 3、等待信号量元素值+1的进程数; 4、等待信号量元素值为0的进程数; 二、主要函数 1.1 创建信号量 int semget( key_t key, //标识信号量的关键字,有三种方法:1、使用IPC——PRIVATE让系统产生, // 2、挑选一个随机数,3、使用ftok从文件路径名中产生 int nSemes, //信号量集中元素个数 int flag //IPC_CREAT;IPC_EXCL 只有在信号量集不存在时创建 ) 成功:返回信号量句柄 失败:返回-1 1.2 使用ftok函数根据文件路径名产生一个关键字 key_t ftok(const char *pathname,int proj_id); 路径名称必须有相应权限 1.3 控制信号量 int semctl( int semid, //信号量集的句柄 int semnum, //信号量集的元素数 int cmd, //命令 /*union senum arg */... // ) 成功:返回相应的值 失败:返回-1 命令详细说明: cmd: IPC_RMID 删除一个信号量 IPC_EXCL 只有在信号量集不存在时创建 IPC_SET 设置信号量的许可权 SETVAL 设置指定信号量的元素的值为 agc.val GETVAL 获得一个指定信号量的值 GETPID 获得最后操纵此元素的最后进程ID GETNCNT 获得等待元素变为1的进程数 GETZCNT 获得等待元素变为0的进程数 union senum 定义如下: union senum{ int val; struct semid_ds *buf; unsigned short * array; }agc; 其中 semid_ds 定义如下: struct semid_ds{ struct ipc_pem sem_pem; //operation pemission struct time_t sem_otime; //last semop()time time_t sem_ctime; //last time changed by semctl() struct sem *sembase; //ptr to first semaphore in array struct sem_queue *sem_pending; //pending operations struct sem_queue *sem_pending_last; //last pending operations struct sem_undo *undo; //undo requests on this arrary unsigned short int sem_nsems; //number of semaphores in set }; 1.4 对信号量 +1 或 -1 或测试是否为0 int semop( int semid, struct sembuf *sops, //指向元素操作数组 unsigned short nsops //数组中元素操作的个数 ) 结构 sembuf 定义 sembuf{ short int sem_num; //semaphore number short int sem_op; //semaphore operaion short int sem_flg //operation flag }; 三、例子: 2.1 服务器
#include <sys/sem.h> #include <sys/ipc.h>
#define SEGSIZE 1024 #define READTIME 1 union semun { int val; struct semid_ds *buf; unsigned short *array; } arg; //生成信号量 int sem_creat(key_t key) { union semun sem; int semid; sem.val = 0; semid = semget(key,1,IPC_CREAT|0666); if (-1 == semid){ printf("create semaphore error\n"); exit(-1); } semctl(semid,0,SETVAL,sem); return semid; } //删除信号量 void del_sem(int semid) { union semun sem; sem.val = 0; semctl(semid,0,IPC_RMID,sem); }
//p int p(int semid) { struct sembuf sops={0,+1,IPC_NOWAIT}; return (semop(semid,&sops,1)); } //v int v(int semid) { struct sembuf sops={0,-1,IPC_NOWAIT}; return (semop(semid,&sops,1)); } int main() { key_t key; int shmid,semid; char *shm; char msg[7] = "-data-"; char i; struct semid_ds buf; key = ftok("/",0); shmid = shmget(key,SEGSIZE,IPC_CREAT|0604); if (-1 == shmid){ printf(" create shared memory error\n"); return -1; } shm = (char *)shmat(shmid,0,0); if (-1 == (int)shm){ printf(" attach shared memory error\n"); return -1; } semid = sem_creat(key); for (i = 0;i <= 3;i++){ sleep(1); p(semid); sleep(READTIME); msg[5] = ''''0'''' + i; memcpy(shm,msg,sizeof(msg)); sleep(58); v(semid); } shmdt(shm); shmctl(shmid,IPC_RMID,&buf); del_sem(semid); return 0; //gcc -o shm shm.c -g } 2.2 客户端 #include <sys/sem.h> #include <time.h> #include <sys/ipc.h>
#define SEGSIZE 1024 #define READTIME 1 union semun { int val; struct semid_ds *buf; unsigned short *array; } arg;
// 打印程序执行时间 void out_time(void) { static long start = 0; time_t tm; if (0 == start){ tm = time(NULL); start = (long)tm; printf(" now start ...\n"); } printf(" second: %ld \n",(long)(time(NULL)) - start); }
//创建信号量 int new_sem(key_t key) { union semun sem; int semid; sem.val = 0; semid = semget(key,0,0); if (-1 == semid){ printf("create semaphore error\n"); exit(-1); } return semid; }
//等待信号量变成0 void wait_v(int semid) { struct sembuf sops={0,0,0}; semop(semid,&sops,1); }
int main(void) { key_t key; int shmid,semid; char *shm; char msg[100]; char i; key = ftok("/",0); shmid = shmget(key,SEGSIZE,0); if(-1 == shmid){ printf(" create shared memory error\n"); return -1; } shm = (char *)shmat(shmid,0,0); if (-1 == (int)shm){ printf(" attach shared memory error\n"); return -1; } semid = new_sem(key); for (i = 0;i < 3;i ++){ sleep(2); wait_v(semid); printf("Message geted is: %s \n",shm + 1); out_time(); } shmdt(shm); return 0; // gcc -o shmc shmC.c -g }
没有相关教程
|