Linux 编程 --进程间通信

目录

一、进程认知

二、进程间通信方式(IPC)

一、进程认知

         将一个静态程序文件(Program)追加到内存当中,让CPU逐条执行做出相应动作,动态的进程(Process动态变化的过程)。

二、进程间通信方式(IPC)

1、无名管道(PIPE)和有名管道(FIFO)

1)PIPE:无名字,不能用open()打开操作,半双工,只能用于亲缘进程间,对写操作不做任何保护,若多进程或多线程对其进行写操作,会造成数据践踏。

int	pipe (int fildes[2]);  //fd[0]读,fd[1]写

//pipe不能用lseek定位,像是看不见源的水龙头无法定位

2)FIFO:有名字,可以用opne()来进行文件描述符操作,支持多者同时写入,跟普通文件一样可以使用write()/read()来进行读写。

int mkfifo(const char *pathname, mode_t mode); //FIFO文件名,文件权限

//不能使用lseek()定位,原因同PIPE一样

2、信号(SIGNAL)

1)非实时信号:前面31个信号(1-31)

2)实时信号:后面31个信号(34-64)

//信号是异步性的,操作要谨慎

void 	(*signal (int __sig, void (*__handler)(int)))(int);  //捕捉指定信号

int	kill (pid_t, int);  //进程发送指定信号

3、消息队列(MSG)

1)使用方法:

1-1)发送者(snd):获取消息队列的ID;将数据放入附带标识的特殊结构体里面,发送给消息队列;

1-2)接收者(rcv):获取消息队列ID;将指定标识的消息读出;

带消息标识的特殊管道通信方式,当snd,rcv不再使用消息队列时,及时删除释放系统资源;

int msgget (key_t __key, int __msgflg);  //获取消息队列ID

key的获取ftok()


/* Template for struct to be used as argument for `msgsnd' and `msgrcv'.  */
struct msgbuf
  {
    long int mtype;		/* type of received/sent message 不能是0L*/
    char mtext[1];		/* text of the message */
  };

int msgsnd (int __msqid, __const void *__msgp, size_t __msgsz,
		   int __msgflg);  //发送

ssize_t msgrcv (int __msqid, void *__msgp, size_t __msgsz,
		       long int __msgtyp, int __msgflg);  //接收

/* Message queue control operation.  */
int msgctl (int __msqid, int __cmd, struct msqid_ds *__buf); //设置或获取消息队列的相关属性
 

消息队列不适用于海量数据传输,因为数据需从用户态转折到内核态,效率不高; 

4、共享内存(SHM)

1)使用方法

1-1)获取共享内存对象的ID;

1-2)将共享内存映射;

1-3)不再使用时解除映射关系;

1-4)没有进程使用共享内存时,删除。

int shmget (key_t __key, size_t __size, int __shmflg);  //获取共享内存ID

//size = 1024 整数倍

/* Attach shared memory segment.  共享内存映射*/
void *shmat (int __shmid, __const void *__shmaddr, int __shmflg);  //将shmaddr设置为NULL,简单移植性强

/* Detach shared memory segment.  解除映射*/
extern int shmdt (__const void *__shmaddr);

int shmctl (int __shmid, int __cmd, struct shmid_ds *__buf);  //获取或设置共享内存的相关属性

进程间通信效率最高的方式,需结合信号量等同步互斥机制一起使用;

5、信号量(SEM)

见线程的信号量描述,作为进程之间以及同一进程的不同线程之间的同步和互斥手段;

6、socket套接字

//来自于zqixiao_09文章摘录

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 8888
#define MAXSIZE 128
 
int main()
{
	int i,nbyte;
	int listenfd, confd, maxfd;
	char buffer[MAXSIZE];
	fd_set global_rdfs, current_rdfs;
	struct sockaddr_in addr,clientaddr;
	int addrlen = sizeof(struct sockaddr_in);
	int caddrlen = sizeof(struct sockaddr_in);
 
	if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("socket error");
		exit(-1);
	}
	else
	{
		printf("socket successfully!\n");
		printf("listenfd : %d\n",listenfd);
	}
 
	memset(&addr, 0 ,addrlen);
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	if(bind(listenfd,(struct sockaddr *)&addr,addrlen) == -1)
	{
		perror("bind error");
		exit(-1);
	}
	else
	{
		printf("bind successfully!\n");
		printf("listen port:%d\n",PORT);
	}
 
	if(listen(listenfd,5) == -1)
	{
		perror("listen error");
		exit(-1);
	}
	else
	{
		printf("listening...\n");
	}
 
	maxfd = listenfd;
	FD_ZERO(&global_rdfs);
	FD_SET(listenfd,&global_rdfs);
 
	while(1)
	{
		current_rdfs = global_rdfs;
		if(select(maxfd + 1,¤t_rdfs, NULL, NULL,0) < 0)
		{
			perror("select error");
			exit(-1);
		}
		
		for(i = 0; i <= listenfd + 1; i++)
		{
			if(FD_ISSET(i, ¤t_rdfs))
			{
				if(i == listenfd)
				{
					if((confd = accept(listenfd,(struct sockaddr *)&clientaddr,&caddrlen)) == -1)
					{
						perror("accept error");
						exit(-1);
					}
					else
					{
						printf("Connect from [IP:%s PORT:%d]\n",
								inet_ntoa(clientaddr.sin_addr),clientaddr.sin_port);
						FD_SET(confd,&global_rdfs);
						maxfd = (maxfd > confd ? maxfd : confd);
					}
				}
				else
				{
					if((nbyte = recv(i, buffer, sizeof(buffer),0)) < 0)
					{
						perror("recv error");
						exit(-1);
					}
					else if(nbyte == 0)
					{
						close(i);
						FD_CLR(i,&global_rdfs);
					}
					else
					{
						printf("recv:%s\n",buffer);
						send(i, buffer, sizeof(buffer),0);
					}
				}
			}
		}
	}
 
	return 0;
}

应用于不同主机之间的进程间通信。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值