linux基础——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;
}

  • 执行结果
    在这里插入图片描述
发布了102 篇原创文章 · 获赞 27 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_37596943/article/details/104201212