C++笔记--Linux编程(11)-进程通信

目录

无名管道

无名管道

打开和关闭管道

读写管道

读写无名管道示例

有名管道(FIFO)

shell命令可以建立有名管道

 方法创建fifo

mkfifo函数示例

删除fifo

unlink函数示例

打开和关闭FIFO

读FIFO例子

写FIFO例子

mmap映射

映射关系可以分为两种


无名管道

无名管道

        无名管道是半双工的,就是对于一个管道来讲,只能读,或者写

        无名管道只能在相关的、有共同祖先的进程间使用。

        一个fork或者exec调用创建的子进程继承了父进程的文件描述符。

打开和关闭管道

int pipe(int filedes[2]);

在你从一个管道中读出或者写入数据,这个管道必须存在。

如果成功建立了管道,则会打开两个文件描述符,并把它们的值保存在一个整数数组中

第一个文件描述符用于读取数据,第二个文件描述符用于写入数据

如果出错返回-1,同时设置errno 关闭一个管道用close()函数

读写管道

        读写管道与读写普通文件方式一样,调用write与read函数即可

        几乎不会在一个进程中打开一个管道仅供进程自己使用,管道是用来交换数据的。

        因为一个进程已经能够访问它要通过管道共享的数据,和自己共享数据是没有意义的。

        试图对一个管道的两端进行读写操作是一个严重的错误。

读写无名管道示例

int main(int arg, char * args[])
{
	int fd[2];char buf[100];int len;
	pipe(fd);
	memset(buf, 0, sizeof(buf));
	int pid = fork();
	if (pid == 0)
	{
		close(fd[1]);
		while((len = read(fd[0], buf, sizeof(buf))) >0)
		{
			write(STDOUT_FILENO, buf, len);
		}
		close(fd[0]);
	}
	else
	{
		close(fd[0]);
		strcpy(buf, "hello world\n");
		write(fd[1], buf, sizeof(buf));
		close(fd[1]);
		waitpid(pid, NULL, 0);
	}
	return 0;
}

有名管道(FIFO)

        有名管道是持久稳定的。 它们存在于文件系统中

        FIFO比无名管道作用更大,因为它们能让无关联的进程之间交换数据

shell命令可以建立有名管道

mkfifo [option] name

        mkfifo创建一个名为name的有名管道

        mkfifo fifo1。 创建一个有名管道fifo1。

        cat < fifo1。 通过cat命令从fifo1中读取数据。

        ls > fifo1。 将ls命令输出的结果写入fifo1中

 方法创建fifo

int mkfifo(const char *pathname, mode_t mode)

函数执行成功返回0,否则返回-1,并设置变量errno。

mkfifo函数示例

int main(int arg, char *args[])
{
	mkfifo("fifo1", 0666);
	return 0;
}

八进制数0666转化为二进制后为110110110,代表读写权限为rw-rw-rw- 

删除fifo

int unlink(const char *pathname);

函数执行成功返回0,否则返回-1,并设置变量errno。

unlink函数示例

int main(int arg, char * args[])
{
	int i = unlink("fifo1");
	if (i == -1)
	{
		printf(strerror(errno));
	}
	return 0;
}

打开和关闭FIFO

int open(const char *pathname, int flags); int close(int fd);

Linux的一切都是文件这一抽象概念的优势,打开和关闭FIFO和打开关闭一个普通文件操作是一样的。

FIFO的两端使用前都必须要打开。

open中如果参数flags为O_RDONLY将阻塞open调用,一直到另一个进程为写入数据打开FIFO为止。相同的,O_WRONLY也导致阻塞一直到为读出数据打开FIFO为止

读FIFO例子

int main(int arg, char * args[])
{
	int len = 0;
	char buf[100];
	memset(buf, 0, sizeof(buf));
	int fd = open("fifo1", O_RDONLY);
	while ((len = read(fd, buf, sizeof(buf))) > 0)
	{
		printf("%s\n", buf);
	}
	close(fd);
	return 0;
}

写FIFO例子

int main(int arg, char * args[])
{
	int len = 0;
	char buf[100];
	memset(buf, 0, sizeof(buf));
	int fd = open("fifo1", O_WRONLY);
	while(1)
	{
		scanf("%s", buf);
		if (buf[0] == '0')
			break;
		write(fd, buf, sizeof(buf));
	}
	close(fd);
	return 0;
}

mmap映射

映射关系可以分为两种

1、文件映射
        磁盘文件映射进程的虚拟地址空间,使用文件内容初始化物理内存。
2、匿名映射
        初始化全为0的内存空间

而对于映射关系是否共享又分为
1、私有映射(MAP_PRIVATE)
多进程间数据共享,修改不反应到磁盘实际文件,是一个copy-on-write(写时复制)的映射方式。
2、共享映射(MAP_SHARED)
多进程间数据共享,修改反应到磁盘实际文件中

总结起来有4种组合
1、私有文件映射
多个进程使用同样的物理内存页进行初始化,但是各个进程对内存文件的修改不会共享,也不会反应到物理文件中

2、私有匿名映射
mmap会创建一个新的映射,各个进程不共享,这种使用主要用于分配内存(malloc分配大内存会调用mmap)。
例如开辟新进程时,会为每个进程分配虚拟的地址空间,这些虚拟地址映射的物理内存空间各个进程间读的时候共享,写的时候会copy-on-write。

3、共享文件映射
多个进程通过虚拟内存技术共享同样的物理内存空间,对内存文件 的修改会反应到实际物理文件中,他也是进程间通信(IPC)的一种机制。

4、共享匿名映射
这种机制在进行fork的时候不会采用写时复制,父子进程完全共享同样的物理内存页,这也就实现了父子进程通信(IPC)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值