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