文章目录
IPC进程间通讯
消息队列
向消息队列发送消息和接收消息
代码示例
共享内存
代码示例
信号量集
代码示例
IPC进程间通讯
使用命令ipcs可以查看IPC的对象。
ftok
#include <sys/types.h> #include <sys/ipc.h> key_t ftok(const char *pathname, int proj_id); 功能:转换pathname和proj_id为一个key值 参数: pathname:指定文件的名字 proj_id:一个整数,这个整数的低8位不能为0 返回值: 成功 key值返回 -1 失败 errno被设置
1.第一步,获取一个键值。
2. 第二步,通过键值获取一块内存,将这块内存的id返回。
3. 第三部,通过内存id来操作这块内存。
代码示例
- ftok.c
#include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> int main(void){ key_t key; //获取键值 key=ftok("hello",32); if(key==-1){ perror("ftok"); return 1; } printf("key=%d\n",key); return 0; }
- 执行结果
消息队列
通过键值获取一块内存,将这块内存的id返回,需要使用到msgget获取内核内存的id。
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgget(key_t key, int msgflg); 功能:获取一个消息队列的id 参数: key:fotk(3)获取到的键值 msgflg: IPC_CREAT: IPC_EXCL: mode: 指定了消息队列的权限 返回值: -1 失败 errno被设置 成功返回消息队列的id
代码示例
通过键值获取消息队列的id
- msgget.c
#include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int main(void){ key_t key; //获取键值 key=ftok("hello",31); if(key==-1){ perror("ftok"); return 1; } printf("key=%x\n",key); //通过键值获取消息队列的id int msqid=msgget(key,IPC_CREAT|0664); if(msqid==-1){ perror("msgget"); return 2; } printf("msgqid=%d\n",msqid); return 0; }
- 执行结果
向消息队列发送消息和接收消息
msgsnd
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgsnd(int msqid,const void *msgp,size_t msgsz,\ int msgflg); 功能:向消息队列发送消息 参数: msqid:指定了要操作的消息队列的id msgp:指向struct msgbuf类型的变量的指针 msgsz:是mtext的长度 msgflg: IPC_NOWAIT 在空间不够的情况下,非阻塞等待,立即返回错误 0 空间不够的情况下,等待空间充足才解除阻塞 返回值: 0 成功 -1 失败 errno被设置
msgrcv
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz,\ long msgtyp,int msgflg); 功能:从消息队列中获取消息 参数: msqid:指定了消息队列的id msgp:指向了获取到的消息 msgsz:是mtext的长度 msgtyp:消息的类型 msgflg: IPC_NOWAIT:如果消息队列中没有消息,立即返回 0:如果消息队列中没有消息,阻塞等待 返回值: -1 错误 errno被设置 获取到的消息体的字节数
代码示例
将一个消息放入消息队列中。
- processA.c
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> typedef struct msgbuf{ long mtype; char mtext[256]; }msgbuf_t; int main(void){ key_t key; msgbuf_t mb;//消息类型的变量 //获取key值 key=ftok("hello",31); if(key==-1){ perror("ftok"); return 1; } //获取消息队列的id int msqid=msgget(key,IPC_CREAT|0664); if(msqid==-1){ perror("msgget"); return 2; } //初始化消息 mb.mtype=3;/*must be >0*/ strcpy(mb.mtext,"this is test\n"); //向消息队列中写入消息 int s=msgsnd(msqid,&mb,strlen(mb.mtext)+1,0); if(s==-1){ perror("msgsnd"); return 3; } return 0; }
从消息队列中获取消息并显示
- processB.c
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> typedef struct msgbuf{ long mtype; char mtext[256]; }msgbuf_t; int main(void){ key_t key; msgbuf_t mb;//消息类型的变量 //获取key值 key=ftok("hello",31); if(key==-1){ perror("ftok"); return 1; } //获取消息队列的id int msqid=msgget(key,IPC_CREAT|0664); if(msqid==-1){ perror("msgget"); return 2; } //从消息队列中获取消息 int s=msgrcv(msqid,&mb,256,3,0); if(s==-1){ perror("msgrcv"); return 3; } printf("%s",mb.mtext); return 0; }
- 执行结果
共享内存
根据键值获取共享内存的id,通过shmget获取共享内存id。
int shmget(key_t key, size_t size, int shmflg);
#include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); 功能: 参数: key:ftok(3)返回的键值 size:指定了共享内存的尺寸 shmflg: IPC_CREAT:指定创建共享内存段 IPC_EXCL: mode: 返回值: -1 错误 返回共享内存段的id
将共享内存映射到进程的虚拟地址空间中,使用shmat
shmat(2)
#include <sys/types.h> #include <sys/shm.h> void *shmat(int shmid, const void *shmaddr, int shmflg); 功能:将共享内存绑定到进程的地址空间里 参数: shmid:共享内存的id shmaddr:指定了进程绑定共享内存的地址。指定为NULL,有系统做选择 shmflg: SHM_RDONLY:共享内存段只读 返回值: 返回和共享内存段绑定的地址 (void *) -1 错误 errno被设置
*int shmdt(const void shmaddr);
功能:解除和共享内存段的绑定 参数: shmaddr:指定了要解除的共享内存段在进程中的地址 返回值: 0 成功 -1 失败 errno被设置
代码示例
创建共享内存段。
- shm.c
#include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> int main(void){ key_t key; //获取键值 key=ftok("hello",41); if(key==-1){ perror("ftok"); return 1; } printf("key:%d\n",key); //根据键值获取shmid int shmid=shmget(key,1024,\ IPC_CREAT|0664); if(shmid==-1){ perror("shmget"); return 2; } printf("获取到共享内存%d\n",shmid); return 0; }
- 执行结果
使用共享内存完成进程间通信:
- shmA.c
#include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> #include <string.h> int main(void){ key_t key; //获取键值 key=ftok("hello",41); if(key==-1){ perror("ftok"); return 1; } printf("key:%d\n",key); //根据键值获取shmid int shmid=shmget(key,1024,\ IPC_CREAT|0664); if(shmid==-1){ perror("shmget"); return 2; } printf("获取到共享内存%d\n",shmid); //将共享内存映射到进程的虚拟地址空间 void *p=shmat(shmid,NULL,0); if(p==(void *) -1){ perror("shmat"); return 3; } //拷贝字符串到共享内存段 strcpy(p,"hello tarena\n"); //解除绑定 shmdt(p); return 0; }
- shmB.c
#include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> #include <string.h> int main(void){ key_t key; //获取键值 key=ftok("hello",41); if(key==-1){ perror("ftok"); return 1; } printf("key:%d\n",key); //根据键值获取shmid int shmid=shmget(key,1024,\ IPC_CREAT|0664); if(shmid==-1){ perror("shmget"); return 2; } printf("获取到共享内存%d\n",shmid); //将共享内存映射到进程的虚拟地址空间 void *p=shmat(shmid,NULL,0); if(p==(void *) -1){ perror("shmat"); return 3; } //将共享内存段的内容输出到显示器 printf("%s",(char *)p); //解除绑定 shmdt(p); return 0; }
- 执行结果
信号量集
具体参考代码示例
代码示例
- mycp.c
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> void copy_file(int s,int d){ int r,w; char buf[1024]; char *tmp; r=read(s,buf,1024); while(r>0){ tmp=buf; while(1){//将读出的内容完全写入到目标文件 w=write(d,tmp,r); r=r-w; tmp+=w; if(r==0)break; } r=read(s,buf,1024); } return; } int main(int argc,char *argv[]){ int s_fd,d_fd; //以只读方式打开源文件 s_fd=open(argv[1],O_RDONLY); if(s_fd==-1){ perror("open s"); return 1; } //以写的方式打开目标文件 d_fd=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0664); if(d_fd==-1){ perror("open d"); return 2; } copy_file(s_fd,d_fd); close(s_fd); close(d_fd); return 0; }
- 执行结果