系统编程
目录1.管道通信
1.1匿名管道(pipe)
//创建子线程
pid_t fork(void);
/***************************************
*返回值 成功(父进程) > 0 / (子进程) 0 失败 -1(父进程,不创建子进程)
*注意事项 创建子进程后,子进程会拷贝所有父进程的数据段和代码段
***************************************/
//创建一个匿名管道
int pipe(int pipefd[2]);
/***************************************
*参数 @pipefd[2] 指定的数组 pipefd[2]
*返回值 成功:0 失败:-1
*注意事项 pipefd[0] 管道的读取端
* pipefd[1] 管道的写入端
/***************************************
由于匿名管道没有名称,所以只适合在有亲缘关系的进程中使用,常用于于父子进程,但是匿名管道不保证数据的原子性
1.2命名管道(fifo)
//创建一个有名管道
int mkfifo(const char* pathname,mode_t mode);
/*********************************************
*参数 @pathname 文件路径
* @mode 文件权限
*返回值 成功:0 失败:-1
*注意事项 任何进程都可以像普通文件一样打开它进行读取写入
*********************************************/
2.消息队列
//创建键值key
key_t ftok(const char *pathname, int proj_id);
/*********************************************
*参数 @pathname 系统存在且能访问的一个文件路径
* @proj_id 项目id,由用户指定,
*返回结果 成功 key(键值) 失败 -1
*注意事项 ftok()函数生成的键值key的组成:proj_id的低8位+ 设备编号的低8位+ inode编号
* 的低16位
*********************************************/
//创建或者打开消息队列
int msgget(key_t key, int msgflg);
/*********************************************
*参数 @key 键值
* @msgflg 标志和消息队列的权限,常用权限 0644
* IPC_CREAT 消息队列不存在则创建
* IPC_EXCL 消息队列存在则文件调用失败
*返回结果 成功 消息队列表示符 失败 -1
*注意事项 第二个参数常常用 IPC_CREAT|IPC_EXCL|0644
*********************************************/
//向指定的消息队列发送信息
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
/*********************************************
*参数 @msqid 消息队列的标识符
* @msgp 存储消息队列信息数据的结构体
* @msgsz 消息正文的大小
* @msgflg 消息队列的标志,默认为阻塞状态(则填0),IPC_NOWAIT表示不阻塞
*返回结果 成功 0 失败 -1
*注意事项 消息队列默认的属性是阻塞的,当带写入的信息长度大于信息队列剩余空间时,默认阻
* 塞,直到消息队列的容量足够容纳时会解除阻塞。
* 当消息队列的属性为非阻塞时(IPC_NOWAIT)且待写入的消息的长度大于消息队列剩余
* 空间,则直接返回并报错
*********************************************/
//信息数据
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
//向指定消息队列读取信息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
/*********************************************
*参数 @msqid 消息队列标识符
* @msgp 指向信息数据的结构体指针
* @msgsz 存放消息的缓存地址大小
* @msgtyp 接收消息的类型
* >0 读取指定类型为 msgtyp 的第一个信息若(msgflg被配置了
* MSG_EXCEPT则读取除了类型为msgtyp的第一个信息)
* <0 读取第一个类型小于等于msgtyp绝对值的最小类型信息
* =0 不区分类型直接读取第一个信息
* @msgflg 接收消息时的属性( 0 为默认属性)
* PC_NOWAIT 非阻塞状态
* MSG_EXCEPT 读取除了msgtyp之外的第一个信息
* MSG_NOERROR 如果嗲读取的信息字节比msgsz大,则只返回msgsz部
* 分,其他丢弃
*返回结果 成功 实际读取的消息正文字节数 失败 -1
*注意事项 msgsz类型就是msgbuf结构体中mtype所存储的信息
*********************************************/
//获取信息队列的属性,设置消息队列的属性,删除消息队列等
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
/*********************************************
*参数 @msqid 消息队列标识符
* @cmd 指定要执行的命令
* IPC_STAT 获取消息队列的属性,并存放在buf中
* IPC_SET 设置消息队列的属性,使用buf结构体的值来更新消息队列的属性
* IPC_RMID 删除消息队列
* @buf 传递或者接收信息队列的属性
*返回结果 成功 cmd设置为以上这三种属性返回0(其他属性请看man手册) 失败 -1
*注意事项 当不需要传递或者接收信息队列的属性,可设置为NULL
*********************************************/
3. 共享内存
// 申请共享内存
int shmget(key_t key, size_t size, int shmflg);
/*********************************************
*参数 @key 键值
* @size 申请的共享内存段的大小
* @shmflg 内存段的标志,常用有IPC_CREAT和IPC_EXCL
*返回结果 成功 共享内存标识符 失败 -1
*注意事项 申请成功的共享内存段里面存储的内容会被自动初始化为0,
* 并且内核会为每一块创建的共享内存分配一个shmid_ds结构体来记录共享内存的属性和信息
* (man手册查看shmctl可以找到该结构体)
*********************************************/
//映射共享内存
void *shmat(int shmid, const void *shmaddr, int shmflg);
/*********************************************
*参数 @shmid 内存段标识符
* @shmaddr 指定映射后的地址,由系统指定,一般为NULL
* @shmflg 共享内存的属性,0为默认(可读可写)
*返回结果 成功 返回共享内存段的地址
* 失败 返回(void*)-1
*注意事项 只要共享内存的shmid一样,则访问的是同一段共享内存
*********************************************/
//结束共享内存映射
int shmdt(const void *shmaddr);
//控制共享内存
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
/*********************************************
*参数 @shmid 共享内存标识符
* @cmd 指定要执行的命令
* IPC_STAT 获取共享内存的属性,并存放在buf中
* IPC_SET 设置共享内存的属性,使用buf结构体的值来更新共享内存的属性
* PC_RMID 删除共享内存
* @buf 传递或者接收共享内存的属性
*返回结果 成功 cmd设置为以上这三种属性返回0(其他属性请看man手册) 失败 -1
*注意事项 当不需要传递或者接收共享内存的属性,可设置为NULL
*********************************************/
4.信号量
注意:信号量的目的是为了控制信息的同步和互斥。而不是为了传输数据
pv操作:p操作——申请信号量 v操作——归还信号量
临界资源:被多个进程或者一个进程里的多个线程访问的资源
临界区:访问临界资源的代码段
进入临界区:开始执行代码段
退出临界区:临界区的代码段执行完毕
死锁(DeadLock):只申请资源,不释放资源,就会导致所有进程阻塞
//创建或者打开信号量
int semget(key_t key, int nsems, int semflg);
/**********************************************
*参数 @key: 由ftok生成的键值
* @nsems: 信号量中的元素数量
* @semfig: 操作的权限,常见有 IPC_CREAT IPC_EXCL IPC_NOWAIT 需要或上文件权限常见为0644
*返回值 成功 信号量标识符 失败 -1
*注意事项 IPC_CREAT 没有就创建信号量
* IPC_EXCL 与IPC_CREAT一起使用时,如果指定的键值已存在,则返回错误
* IPC_NOWAIT 在等待获取信号量资源时,不阻塞进程。如果无法立即获得资源,则直接返回错误。
***********************************************/
//进行pv操作
int semop(int sem_id, struct sembuf *sem_opa, size_t num_sem_ops);
//第二个参数的结构体参数
struct sembuf sem_opa
{
unsigned short sem_num; /* 要操作的信号量在集合中的索引,从0开始计数*/
short sem_op; /* pv操作位,-1 为p操作,+1 为v操作 */
short sem_flg; /* 控制操作的标志位 */
/*SEM_UNDO:使操作可以被撤销,即在进程意外终止时自动撤销操作。
IPC_NOWAIT:如果操作无法立即执行,不要阻塞进程,立即返回并报告错误。
SEM_NOERROR:如果出现错误(如信号量不存在),不要报告错误。*/
}
/***********************************************
*参数 @sem_id 信号量标识符
* @*sem_opa 控制信号量结构体
* @num_sem_ops 进行操作信号量的个数,即sops结构变量的个数,需大于或等于1。最常见设置此值等于1,只完成对一个信号* 量的操作
*返回值 成功 0 失败 -1,并且会设置相应的错误码
*注意事项 P操作:sem_op= -1 <0,使得共享临界资源上锁,其它进程不得访问
* V操作:sem_op= 1 >0,使得共享临界资源解锁,其它进程可以访问
***********************************************/
//该函数用来直接控制信号量信息,初始化和删除信号量
int semctl(int semid, int semnum, int cmd, ...);
//
union semun{
int val;
struct semid_ds *buf;
unsigned short *arry;
struct seminfo *__buf;
};
/***********************************************
*参数 常用前三个参数
* @semid 信号量标识符
* @semnum 是要操作的信号量在集合中的索引,通常为0,表示第一个信号量
* @cmd SETVAL 用联合体中val成员的值设置信号量集合中单个信号量的值
* GETVAL 返回信号量集合内单个信号量的值
* IPC_STAT 从信号量集上检索semid_ds结构,并存到semun联合体参数的成员buf的地址中
* IPC_SET 设置一个信号量集合的semid_ds结构中ipc_perm域的值,并从semun的buf中取出值
* IPC_RMID 从内核中删除信号量集合
* GETALL 从信号量集合中获得所有信号量的值,并把其整数值存到semun联合体成员的一个指针数组中
* SETALL 与GETALL正好相反
*返回值 成功 >=0 失败 -1
*注意事项
***********************************************/
标签:IPC,int,编程,系统,信号量,队列,key,共享内存
From: https://www.cnblogs.com/waibibabu-/p/18225248