郑州市建设路第二小学网站,建设工程合同包括三种,国内出版社网站建设,android系统下载官网目录 
前言 
一、system V IPC对象图解 
1.流程图解#xff1a; 
编辑 
2.查看linux内核中的ipc对象#xff1a; 二、消息队列 
1.消息队列的原理 
2.消息队列相关的API 
2.1 获取或创建消息队列#xff08;msgget#xff09; 实例代码如下#xff1a; 
2.2 发送消息到消…  
目录 
前言 
一、system V IPC对象图解 
1.流程图解 
编辑 
2.查看linux内核中的ipc对象 二、消息队列 
1.消息队列的原理 
2.消息队列相关的API 
2.1 获取或创建消息队列msgget 实例代码如下 
2.2 发送消息到消息队列中 实例代码如下 
2.3 从消息队列中获取消息   
实例代码如下  2.4 消息队列相关的命令 2.5 管理消息队列 实例代码如下 
三、共享内存 
1.概念 
2.原理图解 
3.相关的api函数 
3.1 创建共享内存对象 实例代码如下 
3.2 映射共享内存   3.3 取消映射 实例代码reader.c如下 实例代码writer.c如下 
实例代码shm.h 如下 3.4 管理共享内存 
实例代码如下  
四、信号灯 信号量 
1.概念 
2.信号灯相关的api函数 
2.1 创建或获取信号灯对象 
实例代码如下 
2.2 实现P操作和V操作   
实例代码如下 
2.3 管理信号灯   
实例代码如下  
总结 前言 
System V IPCInter-Process Communication对象是一种用于在不同进程之间进行通信的机制。它包括三种类型的对象消息队列Message Queue、信号量Semaphore和共享内存Shared Memory。 一、system V IPC对象图解 
1.流程图解 2.查看linux内核中的ipc对象 二、消息队列 
1.消息队列的原理 2.消息队列相关的API 
2.1 获取或创建消息队列msgget 头文件 #include sys/types.h #include sys/ipc.h #include sys/msg.h int msgget(key_t key, int msgflg); //参数1  ----- key                 动态获取key  ftok()                     #include sys/types.h                     #include sys/ipc.h                     key_t ftok(const char *pathname, int proj_id);                     //参数1  ---- 工程目录                     //参数2  ---- 工程编号                     //返回值 ----- 成功返回key值失败-1                静态分配 IPC_PRIVATE //参数2 ------ msgflg如果消息队列不存在需要给出创建的关键字并设置权限 IPC_CREAT | 0666 //返回值 ----- 成功消息队列的ID失败-1     实例代码如下 
int main(void)
{key_t key;int msg_id;//获取key值key  ftok(./,0xa);if(key  0){perror(ftok);exit(1);}//创建或获取消息对象msg_id  msgget(key,IPC_CREAT|0666);if(msg_id  0){perror(msgget);exit(1);}return 0;
} 
2.2 发送消息到消息队列中 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); //参数1 ----- 消息队列的id //参数2 -----  指向struct msgbuf结构体的指针该结构体需要自己定义如下                 struct msgbuf {                    long mtype;       /* message type, must be  0 消息类型*/                    char mtext[1];    /* message data  消息正文*/                 }; //参数3 ---- 要发送的消息的长度  //参数4 ---- msgflg值如下             IPC_NOWAIT  消息没有发送完成函数也会立即返回。             0直到发送完成函数才返回 //返回值 --- 成功0失败-1 实例代码如下 
int main(void)
{key_t key;int msg_id;//获取key值key  ftok(./,0xa);if(key  0){perror(ftok);exit(1);}//创建或获取消息对象msg_id  msgget(key,IPC_CREAT|0666);if(msg_id  0){perror(msgget);exit(1);}//向消息队列中发送消息while(1){bzero(buf,sizeof(buf));printf(请输入消息的类型:);scanf(%ld,buf.mtype);printf(请输入消息:);while(getchar() ! \n);   //清空输入缓冲区fgets(buf.mtext,sizeof(buf.mtext),stdin);buf.mtext[strlen(buf.mtext)-1]  \0;if(msgsnd(msg_id,buf,strlen(buf.mtext),0)  0){perror(msgsnd);exit(1);}}return 0;
} 
2.3 从消息队列中获取消息   ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); //参数1 ----- 消息队列的id //参数2 -----  指向struct msgbuf结构体的指针该结构体需要自己定义如下                 struct msgbuf {                    long mtype;       /* message type, must be  0 消息类型*/                    char mtext[1];    /* message data  消息正文*/                 }; //参数3 ----  mtext的长度 //参数4 ----  msgtyp要接收的消息类型              msgtyp  0 ,表示接收指定类型的消息               msgtyp  0 按先后顺序依次接收不同类型消息              msgtyp  0 优先接收消息类型不大于|msgtyp|的最小类型的消息 //参数5 ---- msgflg值如下             IPC_NOWAIT  消息没有发送完成函数也会立即返回。             0直到发送完成函数才返回 //返回值 --- 成功0失败-1 实例代码如下  
int main(void)
{key_t key;int msg_id;//获取key值key  ftok(./,0xa);if(key  0){perror(ftok);exit(1);}//创建或获取消息对象msg_id  msgget(key,IPC_CREAT|0666);if(msg_id  0){perror(msgget);exit(1);}//从消息队列中获取消息while(1){bzero(buf,sizeof(buf));printf(请输入消息的类型:);scanf(%ld,buf.mtype);if(msgrcv(msg_id,buf,sizeof(buf.mtext),buf.mtype,0)  0){perror(msgsnd);exit(1);}printf(msg:%s\n,buf.mtext);}return 0;
} 2.4 消息队列相关的命令 peterubuntu:~/2308/proc/day04_code$ ipcs -q ------ Message Queues -------- key        msqid      owner      perms      used-bytes   messages 0x0a010356 0          peter      666        61           5 peterubuntu:~/2308/proc/day04_code$ ipcrm -q 0 peterubuntu:~/2308/proc/day04_code$ ipcs -q ------ Message Queues -------- key        msqid      owner      perms      used-bytes   messages 2.5 管理消息队列 int msgctl(int msqid, int cmd, struct msqid_ds *buf);  //参数1 ---- 消息队列ID  //参数2 ---- 功能码                  IPC_STAT读取消息队列的属性并将其保存在buf指向的缓冲区中。                 IPC_SET设置消息队列的属性。这个值取自buf参数。                 IPC_RMID从系统中删除消息队列。      //参数3 ----struct msqid_ds 结构体指针                  struct msqid_ds {                        struct ipc_perm msg_perm;     /* Ownership and permissions */                        time_t          msg_stime;    /* Time of last msgsnd(2) */                        time_t          msg_rtime;    /* Time of last msgrcv(2) */                        time_t          msg_ctime;    /* Time of last change */                        unsigned long   __msg_cbytes; /* Current number of bytes in                                                         queue (nonstandard) */                        msgqnum_t       msg_qnum;     /* Current number of messages                                                         in queue */                        msglen_t        msg_qbytes;   /* Maximum number of bytes                                                         allowed in queue */                        pid_t           msg_lspid;    /* PID of last msgsnd(2) */                        pid_t           msg_lrpid;    /* PID of last msgrcv(2) */                    }; 实例代码如下 
int main(int argc,char **argv)
{int msg_id;msg_id  atoi(argv[1]);if(msgctl(msg_id,IPC_RMID,NULL)  0){perror(msgget);exit(1);}return 0;
} 
三、共享内存 
1.概念 共享内存是一种最为高效的进程间通信方式进程可以直接读写内存而不需要任何数据的拷贝 为了在多个进程间交换信息内核专门留出了一块内存区可以由需要访问的进程将其映射到自己的私有地址空间 进程就可以直接读写这一内存区而不需要进行数据的拷贝从而大大提高的效率。 由于多个进程共享一段内存因此也需要依靠某种同步机制如互斥锁和信号量等  2.原理图解 3.相关的api函数 
3.1 创建共享内存对象 头文件 #include sys/ipc.h #include sys/shm.h int shmget(key_t key, size_t size, int shmflg); //参数1 ---- 动态获取key  ftok()                     #include sys/types.h                     #include sys/ipc.h                     key_t ftok(const char *pathname, int proj_id);                     //参数1  ---- 工程目录                     //参数2  ---- 工程编号                     //返回值 ----- 成功返回key值失败-1                静态分配 IPC_PRIVATE //参数2 ---- 要创建或获取的共享内存的大小 //参数3 ---- 权限IPC_CREAT | 0666 //返回值 ---- 成功共享内存ID失败:-1 实例代码如下 
int main(void)
{key_t key;int shm_id;//获取key值key  ftok(./,0xa);if(key  0){perror(ftok);exit(1);}//创建或获取共享内存对象shm_id  shmget(key,SHM_SIZE, IPC_CREAT|0666);if(shm_id  0){perror(shmget);exit(1);}return 0;
} 
3.2 映射共享内存   void *shmat(int shmid, const void *shmaddr, int shmflg); //参数1 ---- 共享内存ID //参数2 ---- 指定进程虚拟空间的映射的起始地址一般为NULL让系统分配一个起始地址 //参数3 ---- 访问权限SHM_RDONLY共享内存只读                     默认0共享内存可读写 //返回值 --- 成功映射的虚拟空间地址失败-1 3.3 取消映射 int shmdt(const void *shmaddr); //参数 ----映射的虚拟空间的起始地址 //返回值 ----成功0失败:-1 实例代码reader.c如下 
#include shm.hint main(void)
{key_t key;int shm_id;char *buf;//获取key值key  ftok(./,0xa);if(key  0){perror(ftok);exit(1);}//创建或获取共享内存对象shm_id  shmget(key,SHM_SIZE, IPC_CREAT|0666);if(shm_id  0){perror(shmget);exit(1);}//将共享内存映射到进程的虚拟空间中buf  (char*)shmat(shm_id,NULL,0);if(buf  0){perror(shmat);exit(1);}//打印共享内存中的数据while(1){printf(%s,buf);sleep(1);}//解除映射if(shmdt(buf)  0){perror(shmdt);exit(1);}return 0;
} 实例代码writer.c如下 
#include shm.hint main(void)
{key_t key;int shm_id;char *buf;//获取key值key  ftok(./,0xa);if(key  0){perror(ftok);exit(1);}//创建或获取共享内存对象shm_id  shmget(key,SHM_SIZE, IPC_CREAT|0666);if(shm_id  0){perror(shmget);exit(1);}//将共享内存映射到进程的虚拟空间中buf  (char*)shmat(shm_id,NULL,0);if(buf  0){perror(shmat);exit(1);}//向共享内存写数据while(1){printf(请输入字符串:);fgets(buf,SHM_SIZE,stdin);}//解除映射if(shmdt(buf)  0){perror(shmdt);exit(1);}return 0;
} 
实例代码shm.h 如下 
#ifndef __SHM_H__
#define __SHM_H__#include stdio.h
#include unistd.h
#include string.h
#include stdlib.h
#include sys/types.h
#include sys/ipc.h
#include sys/shm.h#define SHM_SIZE  1024#endif3.4 管理共享内存 int shmctl(int shmid, int cmd, struct shmid_ds *buf); //参数1 ---- 共享内存的ID //参数2 ---- 功能码             IPC_STAT  (获取对象属性)             IPC_SET (设置对象属性)             IPC_RMID (删除对象)     //参数3 ----struct shmid_ds 结构体指针             struct shmid_ds {                struct ipc_perm shm_perm;    /* Ownership and permissions */                size_t          shm_segsz;   /* Size of segment (bytes) */                time_t          shm_atime;   /* Last attach time */                time_t          shm_dtime;   /* Last detach time */                time_t          shm_ctime;   /* Last change time */                pid_t           shm_cpid;    /* PID of creator */                pid_t           shm_lpid;    /* PID of last shmat(2)/shmdt(2) */                shmatt_t        shm_nattch;  /* No. of current attaches */                ...            }; 实例代码如下  
int main(int argc,char **argv)
{int shm_id;shm_id  atoi(argv[1]);if(shmctl(shm_id,IPC_RMID,NULL)  0){perror(shmget);exit(1);}return 0;
}四、信号灯 信号量 
1.概念 信号灯(semaphore)也叫信号量。它是不同进程间或一个给定进程内部不同线程间同步的机制。 信号灯种类     posix有名信号灯     posix基于内存的信号灯(无名信号灯)     System V信号灯(IPC对象) 1》 二值信号灯用于表示资源是否可用     值为0或1。与互斥锁类似资源可用时值为1不可用时值为0。 2》 计数信号灯用于表示资源的数量     值在0到n之间。用来统计资源其值代表可用资源数 3》 等待操作也称为P操作     是等待信号灯的值变为大于0然后将其减1 4》 释放操作也称为V操作      用来唤醒等待资源的进程或者线程 5》System V的信号灯是一个或者多个信号灯的一个集合。其中的每一个都是单独的计数信号灯。而Posix信号灯指的是单个计数信号灯   2.信号灯相关的api函数 
2.1 创建或获取信号灯对象 头文件  #include sys/types.h #include sys/ipc.h #include sys/sem.h int semget(key_t key, int nsems, int semflg); //参数1 ---- 动态获取key  ftok()                     #include sys/types.h                     #include sys/ipc.h                     key_t ftok(const char *pathname, int proj_id);                     //参数1  ---- 工程目录                     //参数2  ---- 工程编号                     //返回值 ----- 成功返回key值失败-1                静态分配 IPC_PRIVATE //参数2 ---- 集合中信号灯的个数 //参数3 ---- 访问权限IPC_CREAT | 0666 //返回值 ---- 成功信号灯对象ID失败:-1 实例代码如下 
int main(void)
{key_t key;int sem_id;//获取key值key  ftok(./,0xa);if(key  0){perror(ftok);exit(1);}//创建或获取共享内存对象sem_id  semget(key,1, IPC_CREAT|0666);if(sem_id  0){perror(semget);exit(1);}return 0;
} 
2.2 实现P操作和V操作   int semop(int semid, struct sembuf *sops, size_t nsops); //参数1 ----- 信号灯对象的ID //参数2 ----- 结构体指针                 struct sembuf {                    short  sem_num;  //  要操作的信号灯的编号                    short  sem_op;   //    0 :  等待直到信号灯的值变成0                                                //   1  :  释放资源V操作                                                //   -1 :  分配资源P操作                                       short  sem_flg; // 0,  IPC_NOWAIT,  SEM_UNDO                 }; //参数3 -----nops:  要操作的信号灯的个数 //返回值 ---- 成功0失败-1 实例代码如下 
//1》实现P操作void sem_p(int sem_id,int index){struct sembuf buf  {index,-1,0};if(semop(sem_id,buf,1)  0){perror(semop);exit(1);}}
//2》实现v操作void sem_v(int sem_id,int index){struct sembuf buf  {index,1,0};if(semop(sem_id,buf,1)  0){perror(semop);exit(1);}} 
2.3 管理信号灯   int semctl(int semid, int semnum, int cmd, ...); //参数1 ---- 信号灯对象ID //参数2 ---- 集合中信号灯的编号 //参数3 ---- 功能码             IPC_STAT  ----获取信号灯对象属性             IPC_SET   ----设置信号灯对象属性             IPC_RMID  ----从内核中删除信号灯对象             SETALL      ----设置集合中所有信号灯的值             SETVAL    ----设置集合中编号为semnum的信号灯的值 //参数4 ---- 联合体变量类型如下             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;  /* Buffer for IPC_INFO                                            (Linux-specific) */            }; //返回值 -----成功0失败-1 实例代码如下  
//初始化指定的信号灯
void sem_init(int sem_id,int semnum,int value)
{union semun su;su.val  value;if(semctl(sem_id,semnum,SETVAL,su)  0){perror(semctl);exit(1);}
}
//初始化所有信号灯
void sem_init_all(int sem_id,unsigned short vals[])
{union semun su;su.array  vals;if(semctl(sem_id,0,SETALL,su)  0){perror(semctl);exit(1);}
} 总结 本篇文章针对进程间通信system V IPC对象进行详细讲解希望能够帮到大家 以后还会给大家展现更多关于嵌入式和C语言的其他重要的基础知识感谢大家支持懒大王 希望这篇博客能给各位朋友们带来帮助最后懒大王请来过的朋友们留下你们宝贵的三连以及关注感谢你们