Linux内核设计的艺术-进程间通信

     管道操作分为两部分,一部分是创建管道,另一部分是管道的读写操作。代码如下:

#include <stdio.h>
#include <unistd.h>
int main()
{
	int n,fd[2];
	pid_t pid;
	int i,j;
	char str1[]="ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE
	ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE
	ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE
	ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE
	ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE
	ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE
	ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE
	ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE
	ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE
	ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE
	ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE
	ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE";

	char str2[512];
	if(pipe(fd)<0)
	{
		printf("pipe error\n");
		return -1;
	}
	
	if((pid = fork())<0)
	{
		printf("fork error\n");
		return -1;
	}else if(pid > 0)
	{
		close(fd[0]);
		for(i=0;i<10000;i++)
			write(fd[1],str1,strlen(str1));
	}
	else
	{
		close(fd[1]);
		for(j=0;j<20000;j++)
			read(fd[0],str2,strlen(str2));
	}
}
      父进程把str1中的数据写入管道,子进程从管道中读出数据,其中str1中字符长度为1024字节,即1KB。

      pipe会映射到sys_pipe执行,代码路径:fs/pipe.c

int sys_pipe(unsigned long * fildes)
{
	struct m_inode * inode;
	struct file * f[2];
	int fd[2];
	int i,j;

	j=0;
	for(i=0;j<2 && i<NR_FILE;i++)//准备在file_table[64]中申请两个空闲项
		if (!file_table[i].f_count)//找到空闲项
			(f[j++]=i+file_table)->f_count++;//每项引用计数为1
	if (j==1)
		f[0]->f_count=0;
	if (j<2)
		return -1;
	j=0;
	for(i=0;j<2 && i<NR_OPEN;i++)//准备在*filp[20]中申请两个空闲项
		if (!current->filp[i]) {//找到空闲项
			current->filp[ fd[j]=i ] = f[j];//分别与file_table[64]中申请的两个空闲项挂接
			j++;
		}
	if (j==1)
		current->filp[fd[0]]=NULL;
	if (j<2) {
		f[0]->f_count=f[1]->f_count=0;
		return -1;
	}
	if (!(inode=get_pipe_inode())) {//创建管道文件i节点
		current->filp[fd[0]] =
			current->filp[fd[1]] = NULL;
		f[0]->f_count = f[1]->f_count = 0;
		return -1;
	}
	f[0]->f_inode = f[1]->f_inode = inode;//i节点和表项挂接
	f[0]->f_pos = f[1]->f_pos = 0;//文件指针归0
	f[0]->f_mode = 1;		/* read */ //设置为读模式
	f[1]->f_mode = 2;		/* write */ //设置为写模式
	put_fs_long(fd[0],0+fildes); //将读管道文件句柄返回到用户空间(用户空间变量fd[0])
	put_fs_long(fd[1],1+fildes); //将写管道文件句柄返回到用户空间(用户空间变量fd[1])
	return 0;
}
       创建管道文件i节点,代码如下:

       代码路径:fs/inode.c

struct m_inode * get_pipe_inode(void)
{
	struct m_inode * inode;

	if (!(inode = get_empty_inode()))//申请空闲inode节点
		return NULL;
	if (!(inode->i_size=get_free_page())) {//承载的不再是文件大小,而是内存页面的起始地址
		inode->i_count = 0;
		return NULL;
	}
	inode->i_count = 2;	/* sum of readers/writers */ //引用计数设置为2
	PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;//PIPE_HEAD为写管道指针,PIPE_TAIL为读管道指针,都设置为0
	inode->i_pipe = 1;//设置管道文件属性
	return inode;
}
       代码路径:include/linux/fs.h

#define PIPE_HEAD(inode) ((inode).i_zone[0])
#define PIPE_TAIL(inode) ((inode).i_zone[1])
#define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1))














Linux内核设计的艺术-进程间通信,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。