LINUX_C编程实战—第十章《进程间的通信》-信号量
2017-11-06 18:36
274 查看
好久没更新博客啦,今天工作闲了可以做一个终结啦。
System V信号量的概念:可以理解为一个计数器,主要用于对临界资源的访问,进行PV操作(P操作,获取资源,资源数-1;V操作释放资源,资源数+1);信号量的值大于或等于0时表示可供并发进程使用的资源实体数,小于0表示正在等待使用临界资源的进程数。一般用的最多的为二进制信号量,既值取0,1;
键值:可以理解为IPC的一个中间介值,用来进行通信的,由ftok函数创建;
key_t ftok( const char *pathname, int proj_id); //文件的设备编号和节点
函数调用成功返回key_t键值,出错返回-1;其中在unix系统中,proj_id是子序列,为一个8bit的整数,范围为0-255;
此外要特别注意当pathname指向的文件或目录被删除而且又重新创建时,可以正常创建键值,但键值确和之前的值不一样啦,程序运行不会报错,但无法达到传输通信的作用。确保键值不变,要么保证ftok的文件不被删除,要么不用ftok,指定一个固定的key值
一、信号量的创建:
#include<sys/sem.h>
int semget( key_t key, int nsems, int semflg);//执行成功返回信号量标识符,失败返回-1;
nsems:信号量集中包含的信号量个数;
semflg:操作标识,IPC_CREATE | IPC_EXCL(信号集已有则返回错误)
二、信号量的操作(+-1)
int semop( int semid, struct sembuf *sops, size_t nsops);//成功返回0,失败返回-1;
semid;信号集标识符;
struct sembuf {
ushort sem_num;//信号量在信号量集中的索引
short sem_op;//操作类型,+1(释放资源,资源数加1) or -1(使用资源,资源数减少)
short sem_flg;//操作标志,IPC_NOWAIT 或 0;
}
nsops:将要进行操作的信号量个数,>=1
三、信号集控制: 对信号集中的信号量赋值、取值、删除等;
int semctl( int semid, int semnum,int cmd, union semun);//成功返回0,失败返回-1;
semid:信号量集标识符
semnum:操作信号量在信号量集中的编号,第一个信号量的标号为0;
cmd:取值可为SETVAL、GETVAL、IPC_RMID等;
union semun{
int val;
struct semid_ds *buf;
ushort *array;
struct seminfo *buf;
void *pad;
}
测试代码如下:实现进程间的同步
头文件:sem.h
sem.c文件
makefille文件:
System V信号量的概念:可以理解为一个计数器,主要用于对临界资源的访问,进行PV操作(P操作,获取资源,资源数-1;V操作释放资源,资源数+1);信号量的值大于或等于0时表示可供并发进程使用的资源实体数,小于0表示正在等待使用临界资源的进程数。一般用的最多的为二进制信号量,既值取0,1;
键值:可以理解为IPC的一个中间介值,用来进行通信的,由ftok函数创建;
key_t ftok( const char *pathname, int proj_id); //文件的设备编号和节点
函数调用成功返回key_t键值,出错返回-1;其中在unix系统中,proj_id是子序列,为一个8bit的整数,范围为0-255;
此外要特别注意当pathname指向的文件或目录被删除而且又重新创建时,可以正常创建键值,但键值确和之前的值不一样啦,程序运行不会报错,但无法达到传输通信的作用。确保键值不变,要么保证ftok的文件不被删除,要么不用ftok,指定一个固定的key值
一、信号量的创建:
#include<sys/sem.h>
int semget( key_t key, int nsems, int semflg);//执行成功返回信号量标识符,失败返回-1;
nsems:信号量集中包含的信号量个数;
semflg:操作标识,IPC_CREATE | IPC_EXCL(信号集已有则返回错误)
二、信号量的操作(+-1)
int semop( int semid, struct sembuf *sops, size_t nsops);//成功返回0,失败返回-1;
semid;信号集标识符;
struct sembuf {
ushort sem_num;//信号量在信号量集中的索引
short sem_op;//操作类型,+1(释放资源,资源数加1) or -1(使用资源,资源数减少)
short sem_flg;//操作标志,IPC_NOWAIT 或 0;
}
nsops:将要进行操作的信号量个数,>=1
三、信号集控制: 对信号集中的信号量赋值、取值、删除等;
int semctl( int semid, int semnum,int cmd, union semun);//成功返回0,失败返回-1;
semid:信号量集标识符
semnum:操作信号量在信号量集中的编号,第一个信号量的标号为0;
cmd:取值可为SETVAL、GETVAL、IPC_RMID等;
union semun{
int val;
struct semid_ds *buf;
ushort *array;
struct seminfo *buf;
void *pad;
}
测试代码如下:实现进程间的同步
头文件:sem.h
#ifndef _SEM_H_ #define _SEM_H_ #include<stdio.h> #include<stdlib.h> #include<sys/types.h> #include<sys/ipc.h> #include<sys/sem.h> #include<unistd.h> #include<sys/wait.h> #define PATHNAME "." #define NUMBER 1 int creat_sem(int sems); int init_sem(int semid,int which,int value); int get_sem(); int p_sem(int semid,int which,int *flag); int v_sem(int semid,int which); int destroy(int semid); #endif
sem.c文件
#include "sem.h" /* 创建信号量集*/ int creat_sem(int sems) { key_t key; int semid; /* 利用ftok创建键值*/ key=ftok(PATHNAME,NUMBER); if(key < 0) { perror("ftok error"); exit(1); } /* 创建信号量集函数*/ semid=semget(key,sems,IPC_CREAT | 0666); if(semid < 0) { perror("sem_get error"); exit(1); } return semid; } int get_sem() { /* 利用IPC_CREAT打开已创建的信号量集*/ return creat_sem(2); } /* 不懂为啥还要重复定义共同体,不定义就找不到定义的参数argc*/ union semun { int val; // value for SETVAL struct semid_ds *buf; // buffer for IPC_STAT & IPC_SET unsigned short *array; // buffer for GETALL & SELALL struct seminfo * __buf; // buffer for IPC_INFO }; /* 初始化信号集*/ int init_sem(int semid,int which,int value) { union semun argc; int ret; argc.val = value; /* semctl函数用于初始化编号为which的信号集;亦可用于删除*/ ret = semctl(semid,which,SETVAL,argc); if(ret < 0) { perror("semctl error"); exit(1); } return 0; } /* P操作获取资源,资源数-1 */ int p_sem(int semid,int which,int *flag) { struct sembuf sbuf={which,-1,0}; int ret; ret = semop(semid,&sbuf,1); if(ret < 0) { perror("p_sem error"); /* 出错标志位*/ *flag = 1; exit(0); } return 0; } /* V操作释放资源,资源数+1 */ int v_sem(int semid,int which) { struct sembuf sbuf={which,1,0}; int ret; ret = semop(semid,&sbuf,1); if(ret < 0) { perror("v_sem error"); exit(0); } return 0; } /* 清空信号集*/ int destroy(int semid) { int ret; /* 使用参数IPC_RMID删除信号集*/ ret = semctl(semid,0,IPC_RMID,0); if(ret < 0) { perror("semctl error"); exit(1); } return 0; }主函数:
#include "sem.h" int main(int argc,char **argv) { pid_t pid; int semid,sem_id; /* 创建键值 */ semid = creat_sem(10); init_sem(semid,0,1); pid = fork(); if(pid < 0) { perror("fork error"); exit(0); } else if(pid == 0) { /* 获得键值*/ sem_id = get_sem(); //printf("sem_id=%d\n",sem_id); while(1) { p_sem(sem_id,0); printf("i am child\n"); printf("child_flag=%d\n",_flag); printf("c_hello "); sleep(2); printf("c_world!\n"); sleep(2); v_sem(sem_id,0); } } else { while(1) { /* 获得信号量集中编号为0的资源*/ p_sem(semid,0); /*************临界区 *****************************************************/ printf("i am father\n"); printf("father_flag=%d\n",_flag); printf("f_creat "); sleep(2); printf("sucess!\n"); sleep(2); /*************临界区 *****************************************************/ /* 释放资源*/ v_sem(semid,0); } wait(0); } destroy(semid); return 0; }
makefille文件:
all:main clear main:sem.c main.c gcc sem.c main.c -o main clear: rm -rf *.o运行结果:
相关文章推荐
- LINUX_C编程实战—第十章《进程间的通信》-消息队列
- linux基础编程:进程通信之System V IPC:消息队列,信号量,共享内存
- Linux下的C编程实战(开发平台搭建,文件系统编程,进程控制与进程通信编程,“线程”控制与“线程”通信编程,驱动程序设计,专家问答)
- Linux下的C编程实战(三)――进程控制与进程通信编程 推荐
- UNIX/LINUX编程学习之进程通信--信号量
- Linux下的C编程实战(三)――进程控制与进程通信编程
- LINUX_C编程实战-《进程间的通信》-共享内存
- linux基础编程:进程通信之System V IPC:消息队列,信号量,共享内存
- Linux 进程通信之 ——信号和信号量总结
- linux进程间的通信: 信号量
- linux进程通信--信号量
- linux基础编程:进程通信之管道
- Linux下的C编程实战(四)――“线程”控制与“线程”通信编程
- Linux进程通信--使用信号量
- Linux下C语言编程--进程通信、消息管理
- linux进程间的通信--信号量同步
- Linux下的C编程实战(三)――进程控制与进程通信编程
- linux 进程通信 -- 信号量(更新ing)
- Linux进程间的通信方式:信号量的使用
- linux进程通信-信号量使用