进程间通信共享内存_进程间通信共享内存「建议收藏」

进程间通信共享内存_进程间通信共享内存「建议收藏」一、什么是进程线程?进程通信:在用户空间实现进程通信是不可能的,通过linux内核通信;线程通信:可以在用户空间就可以实现,可以通过全局变量通信

一、什么是进程线程?

进程通信:在用户空间实现进程通信是不可能的,通过linux内核通信;
线程通信:可以在用户空间就可以实现,可以通过全局变量通信。

进程间通信如下:
进程间通信
线程间通信如下:
在这里插入图片描述

二、进程间通信方式有哪些?
	单机模式下的进程通信(只有一个linux内核)
	管道通信:无名管道、有名管道(文件系统中有名)
	信号通信:信号(通知)包括:信号的发送、信号的接收和信号的处理。
	IPC(Inter-Process Communication)通信:共享内存、消息队列和信号灯。

	socket通信:存在于一个网络中两个进程之间的通信(两个Linux内核)。

进程间通信都是基于文件IO思想。

三、管道通信

1、无名管道(pipe)
在这里插入图片描述

管道文件是一个特殊的文件,由队列来实现的。
在文件IO中创建一个文件或打开一个文件是由open函数来实现的,它不能创建管道文件。
只能用 pipe 函数来创建管道。

int pipe(int fd[2]);     -----> unistd.h
参数:
		得到的文件描述符,读端fd[0]用来读,写端fd[2]用来写。
返回值:
		成功:0;
		失败:-1。

注意:
		1)管道是创建在内存中的,进程结束,空间释放,管道就不存在了;
		2)管道中的大小,读完了就不存在了;
		3)如果管道中没有东西,则会阻塞;
		4)如果管道中写满,再写时会进入写阻塞。

无名管道的缺点:不能实现不是父子进程(有亲缘关系)之间的通信。

2、有名管道 (mkfifo)–>管道文件(p)

所谓有名,即文件系统中存在这个一样文件节点,每一个文件节点都有一个inode号,
而且这是一个特殊的文件类型:p 管道类型。
1、创建这个文件节点,不可以通过open函数创建,open函数只能创建普通文件,
	不能创建特殊的文件(管道-mkfifo,套接字-socket,字符设备文件-mknod,块设备文件-mknod,
	符号链接文件-ln -s,目录文件mkdir)

2、管道文件只有inode号,不占磁盘块空间,和套接字、字符设备文件、块设备文件一样。
	普通文件和符号链接文件及目录文件,不仅有inode号,还占磁盘块空间。

3、mkfifo 用来创建管道文件的节点,没有在内核中创建管道。
	只有通过open函数打开这个文件时才会在内核空间创建管道。
int mkfifo(const char *filename, mode_t mode);   创建管道文件 ---->sys.stat.h
参数:
		1)管道文件名;
		2)文件权限,与umask有关。
返回值:
		成功:0;
		失败:-1。

有名管道可以实现无亲缘关系之间的进程通信。
四、信道通信

1、信号的发送(发送信号进程)

int kill(pid_t pid, int sig);     ---->#include <signal.h>、#include <sys/types.h>
	参数:
			1)pid,(linux shell查看进程号:ps -axj)
						  正数:要接收的信号的进程的进程号;
						       0:信号被发送到所有和pid进程在同一个进程组的进程;
						      -1:信号发给所有的进程表中的进程(除了进程号最大的进程外)
			2)sig,信号(linux shell查看所有信号:kill -l)
	返回值:
			成功:0;
			失败:-1
int rasie(int sig); -----> #include <signal.h>、#include <sys/types.h>
	参数:
			sig,信号;
	返回值:
			成功:0;
			出错:-1;
	发送信号给自己,相当于kill(getpid(), sig);
	注意:getpid() -->获取当前进程的进程号;
		 getppid() -->获取当前进程的父进程的进程号。
		 exit(0)  --->包含kill(getppid(), 17);
unsigned int alarm(unsigned int seconds);   ---->#include <unistd.h>
		功能:alarm只会发送SIGALARM信号,alarm会让内核定时一段时间之后发送信号,
		  		   raise会让内核立刻发送信号。
		参数:
			seconds,秒数;
		返回值:
			成功:如果调用此alarm()之前,进程已经设置了闹钟时间,则返回上一个闹钟时间的剩余时		间,否则返回0;
			出错:-1

下面是几种常见的信号:

      SIGHUP :从终端上发出的结束信号.
      SIGINT   :来自键盘的中断信号 ( ctrl + c ) .
      SIGKILL :该信号结束接收信号的进程 .
      SIGTERM:kill 命令发出 的信号.
      SIGCHLD:标识子进程停止或结束的信号.
      SIGSTOP:来自键盘 ( ctrl + z ) 或调试程序的停止执行信号.

2、信号的接收(接收信号进程)

	接收信号的进程,需要满足的条件为这个进程不能结束:sleep。
	pause():使进程处于睡眠状态(S)。
int pause(void); ------>#include <unistd.h>
	返回值:
			成功:0;
			出错:-1

3、信号的处理(接收信号进程)

接收信号的进程,应该怎样处理?处理的方式:
1)进程的默认处理方式(内核为用户进程设置的默认处理方式)
	 A.忽略
	 B.终止进程
	 C.暂停
2)自己的处理方式:
	 自己告诉内核自己需要处理信号的方式。
void (*signal(int signum, void(*handler)(int)))(int); ----->#include <signal.h>
	参数:
			1)signum,指定信号,信号值;
			2)handler:
							SIG_IGN:忽略该信号;
							SIG_DFL:采用系统默认方式处理信号;
							自定义的信号处理函数指针;
	返回值:
			成功:设置之前的信号处理方式;
			出错:-1
五、IPC通信

1、共享内存

打开或创建一个共享内存对象,共享内核在内核是什么样子?
一块缓存,变类似于用户空间的数组或malloc函数分配的空间一样。
所需头文件 #include <sys/types.h>、#include <sys/ipc.h>、#include <sys/shm.h>
函数原型 int shmget(key_t key, int size, int shmflg);
参数 key:IPC_PRIVATE或ftok的返回值;
size:共享内存区大小;
shmflg:同open函数的权限位,也可以用8进制表示法。
返回值 成功:共享内存段标识符–ID–文件描述符;出错:-1.
查看IPC对象:ipcs -m(共享内存) / -q(消息队列) / -s(信号灯);
删除IPC对象:ipcrm -m/-q/-s id;
ftok函数:创建key值。
char ftok(const char *path, char key);
	参数:
			1)文件路径和文件名;
			2)一个字符;
	返回值:
			成功:返回一个key值;
			出错:-1;

IPC_PRIVATE操作时,共享内存的key值都一样,都是0,所以使用ftok来创建。

shmat 将共享内存映射到用户空间中,为了方便用户空间对共享内存的操作,使用地址映射的方式。

void *shmat(int shmid, const void *shmaddr, int shmflg);
	参数:
			1)shmid,ID号
			2)映射到的地址,NULL为系统自动完成的映射;
			3)shmflg, SHM_RDONLY共享内存只读
								 默认是0,表示共享内存可读写。
	返回值:
			成功:映射后的地址;
			失败:NULL
共享内存特点:
	1、共享内存创建之后,一直存在于内核中,直到被删除或系统关闭;
	2、共享内存和管道不一样,读取后,内容仍在共享内存中。
shmdt:将用户空间的进程里的地址映射删除。
int shmdt(const void *shmaddr);
	参数:
			shmaddr,共享内存映射后的地址
	返回值:
			成功:0;
			出错:-1.
shmctl:删除共享内存对象。
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
	参数:
			1)shmid,要操作的共享内存标识符。
			2)cmd:  IPC_STAT(获取对象属性)   ---->实现了ipcs -m命令
							  IPC_SET(设置对象属性)
							  IPC_RMID(删除对象)   ---->实现了ipcrm -m命令
			3)buf:指定IPC_STAT/IPC_SET时用以保存或设置属性
	返回值:
			成功:0;
			出错:-1.
六、消息队列

在这里插入图片描述

msqid_ds 内核维护消息队列的结构体,队列的第一个消息指针msg_first,最后一个消息指针msg_last,消息中有一个成员指针next。
每一个消息中包含有哪些内容:
Data 数据
Length 数据的长度
Type 数据的类型

msgget  -----  消息队列的创建或打开函数
int msgget(key_t key, int flag);   ----> #include <sys/types.h>/#include <sys/ipc.h>/#include <sys/msg.h>
	参数:
			key,和消息队列关联的key值;(两种来源,同共享内存)
			flag,消息队列的访问权限;
	返回值:
			成功:消息队列的ID;
			出错:-1
msgctl:删除消息队列对象。
int msgctl(int msgqid, int cmd, struct msgqid_ds *buf);
	参数:
			1)msgqid,消息队列的队列ID
			2)cmd:  IPC_STAT(获取消息队列属性,并将其保存在buf指向的缓冲区中)   ---->实现了ipcs -q命令
							  IPC_SET(设置消息队列属性,这个值取自buf参数)
							  IPC_RMID(删除消息队列)   ---->实现了ipcrm -q命令
			3)buf:消息队列缓冲区
	返回值:
			成功:0;
			出错:-1.
msgsnd   写消息队列
int msgsnd(int msgqid, const void *msgp, size_t size, int flag);
	参数:
			1)msqid:消息队列的ID;
			2)msgp:指向消息的指针。常用消息结构msgbuf如下:
			   struct msgbuf
				  { 
   
				  	long mtype;    //消息类型
				  	char mtext[N]; //消息正文
				  };
			3)size:发送的消息正文的字节数
			4)flag:IPC_NOWAIT  消息没有发送完成函数也会立即返回;
					 0           直到发送完成函数才返回;
	返回值:
			成功:0;
			出错:-1.
msgrcv  读消息队列
int msgrcv(int msgid, void *msgp, size_t size, long magtype, int flag);
	参数:
		1)msgid:消息队列的ID
		2)msgp:接收消息的缓冲区
		3)size:要接收的消息的字节数
		4)msgtype:  0:接收消息队列中的第一个消息;
					>0:接收消息队列中第一个类型为msgtyp的消息;
					<0:接收消息队列中类型值不大于msgtyp的绝对值且类型值又最小的消息。
		5)flag:    
					0:若无消息会一直阻塞;
					IPC_NOWAIT:若没有消息,进程会立即返回ENOMSG.
	返回值:
		1)成功:接收到的消息的长度;
		2)出错:-1
七、信号灯

所有的函数都是对一个集合的操作。
#include <sys/types.h>、#include <sy/sipc.h>、#include <sys/sem.h>

semget  --->创建/打开信号灯集
int semget(key_t key, int nsems, int semflg);
	参数:	
			1)key: 和信号灯集关联的key值;
			2)nsems: 信号灯集中包含的信号灯数目;
			3)semflg: 信号灯集的访问权限;
	返回值:
			1)成功:信号灯集的ID;
			2)出错:-1.
semctl  ---->删除信号灯集
int semctl(int semid, int semnum, int cmd, ...union semun arg(不是地址));
	参数:
			1)semid:信号灯集ID;
			2)semnum:要修改的信号灯变量(若要删除信号灯集,此参数可以随意选择)
			3)cmd:  GETVAL:获取信号灯的值;
					 SETVAL:设置信号灯的值;
					 IPC_RMID:从系统中删除信号灯集合.
	返回值:
			成功:0;
			出错:-1.

今天的文章进程间通信共享内存_进程间通信共享内存「建议收藏」分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/66514.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注