⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pipe.c

📁 linux1.1源代码
💻 C
字号:
/* *  linux/fs/pipe.c * *  Copyright (C) 1991, 1992  Linus Torvalds */#include <asm/segment.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/signal.h>#include <linux/fcntl.h>#include <linux/termios.h>/* We don't use the head/tail construction any more. Now we use the start/len*//* contruction providing full use of PIPE_BUF (multiple of PAGE_SIZE) *//* Florian Coosmann (FGC)                                ^ current = 1       *//* Additionally, we now use locking technique. This prevents race condition  *//* in case of paging and multiple read/write on the same pipe. (FGC)         */static int pipe_read(struct inode * inode, struct file * filp, char * buf, int count){	int chars = 0, size = 0, read = 0;        char *pipebuf;	if (filp->f_flags & O_NONBLOCK) {		if (PIPE_LOCK(*inode))			return -EAGAIN;		if (PIPE_EMPTY(*inode))			if (PIPE_WRITERS(*inode))				return -EAGAIN;			else				return 0;	} else while (PIPE_EMPTY(*inode) || PIPE_LOCK(*inode)) {		if (PIPE_EMPTY(*inode)) {			if (!PIPE_WRITERS(*inode))				return 0;		}		if (current->signal & ~current->blocked)			return -ERESTARTSYS;		interruptible_sleep_on(&PIPE_WAIT(*inode));	}	PIPE_LOCK(*inode)++;	while (count>0 && (size = PIPE_SIZE(*inode))) {		chars = PIPE_MAX_RCHUNK(*inode);		if (chars > count)			chars = count;		if (chars > size)			chars = size;		read += chars;                pipebuf = PIPE_BASE(*inode)+PIPE_START(*inode);		PIPE_START(*inode) += chars;		PIPE_START(*inode) &= (PIPE_BUF-1);		PIPE_LEN(*inode) -= chars;		count -= chars;		memcpy_tofs(buf, pipebuf, chars );		buf += chars;	}	PIPE_LOCK(*inode)--;	wake_up_interruptible(&PIPE_WAIT(*inode));	if (read)		return read;	if (PIPE_WRITERS(*inode))		return -EAGAIN;	return 0;}	static int pipe_write(struct inode * inode, struct file * filp, char * buf, int count){	int chars = 0, free = 0, written = 0;	char *pipebuf;	if (!PIPE_READERS(*inode)) { /* no readers */		send_sig(SIGPIPE,current,0);		return -EPIPE;	}/* if count <= PIPE_BUF, we have to make it atomic */	if (count <= PIPE_BUF)		free = count;	else		free = 1; /* can't do it atomically, wait for any free space */	while (count>0) {		while ((PIPE_FREE(*inode) < free) || PIPE_LOCK(*inode)) {			if (!PIPE_READERS(*inode)) { /* no readers */				send_sig(SIGPIPE,current,0);				return written? :-EPIPE;			}			if (current->signal & ~current->blocked)				return written? :-ERESTARTSYS;			if (filp->f_flags & O_NONBLOCK)				return written? :-EAGAIN;			interruptible_sleep_on(&PIPE_WAIT(*inode));		}		PIPE_LOCK(*inode)++;		while (count>0 && (free = PIPE_FREE(*inode))) {			chars = PIPE_MAX_WCHUNK(*inode);			if (chars > count)				chars = count;			if (chars > free)				chars = free;                        pipebuf = PIPE_BASE(*inode)+PIPE_END(*inode);			written += chars;			PIPE_LEN(*inode) += chars;			count -= chars;			memcpy_fromfs(pipebuf, buf, chars );			buf += chars;		}		PIPE_LOCK(*inode)--;		wake_up_interruptible(&PIPE_WAIT(*inode));		free = 1;	}	return written;}static int pipe_lseek(struct inode * inode, struct file * file, off_t offset, int orig){	return -ESPIPE;}static int pipe_readdir(struct inode * inode, struct file * file, struct dirent * de, int count){	return -ENOTDIR;}static int bad_pipe_rw(struct inode * inode, struct file * filp, char * buf, int count){	return -EBADF;}static int pipe_ioctl(struct inode *pino, struct file * filp,	unsigned int cmd, unsigned long arg){	int error;	switch (cmd) {		case FIONREAD:			error = verify_area(VERIFY_WRITE, (void *) arg,4);			if (!error)				put_fs_long(PIPE_SIZE(*pino),(unsigned long *) arg);			return error;		default:			return -EINVAL;	}}static int pipe_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait){	switch (sel_type) {		case SEL_IN:			if (!PIPE_EMPTY(*inode) || !PIPE_WRITERS(*inode))				return 1;			select_wait(&PIPE_WAIT(*inode), wait);			return 0;		case SEL_OUT:			if (!PIPE_FULL(*inode) || !PIPE_READERS(*inode))				return 1;			select_wait(&PIPE_WAIT(*inode), wait);			return 0;		case SEL_EX:			if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))				return 1;			select_wait(&inode->i_wait,wait);			return 0;	}	return 0;}/* * Arggh. Why does SunOS have to have different select() behaviour * for pipes and fifos? Hate-Hate-Hate. See difference in SEL_IN.. */static int fifo_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait){	switch (sel_type) {		case SEL_IN:			if (!PIPE_EMPTY(*inode))				return 1;			select_wait(&PIPE_WAIT(*inode), wait);			return 0;		case SEL_OUT:			if (!PIPE_FULL(*inode) || !PIPE_READERS(*inode))				return 1;			select_wait(&PIPE_WAIT(*inode), wait);			return 0;		case SEL_EX:			if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))				return 1;			select_wait(&inode->i_wait,wait);			return 0;	}	return 0;}/* * The 'connect_xxx()' functions are needed for named pipes when * the open() code hasn't guaranteed a connection (O_NONBLOCK), * and we need to act differently until we do get a writer.. */static int connect_read(struct inode * inode, struct file * filp, char * buf, int count){	while (!PIPE_SIZE(*inode)) {		if (PIPE_WRITERS(*inode))			break;		if (filp->f_flags & O_NONBLOCK)			return -EAGAIN;		wake_up_interruptible(& PIPE_WAIT(*inode));		if (current->signal & ~current->blocked)			return -ERESTARTSYS;		interruptible_sleep_on(& PIPE_WAIT(*inode));	}	filp->f_op = &read_fifo_fops;	return pipe_read(inode,filp,buf,count);}static int connect_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait){	switch (sel_type) {		case SEL_IN:			if (!PIPE_EMPTY(*inode)) {				filp->f_op = &read_fifo_fops;				return 1;			}			select_wait(&PIPE_WAIT(*inode), wait);			return 0;		case SEL_OUT:			if (!PIPE_FULL(*inode))				return 1;			select_wait(&PIPE_WAIT(*inode), wait);			return 0;		case SEL_EX:			if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))				return 1;			select_wait(&inode->i_wait,wait);			return 0;	}	return 0;}/* * Ok, these three routines NOW keep track of readers/writers, * Linus previously did it with inode->i_count checking. */static void pipe_read_release(struct inode * inode, struct file * filp){	PIPE_READERS(*inode)--;	wake_up_interruptible(&PIPE_WAIT(*inode));}static void pipe_write_release(struct inode * inode, struct file * filp){	PIPE_WRITERS(*inode)--;	wake_up_interruptible(&PIPE_WAIT(*inode));}static void pipe_rdwr_release(struct inode * inode, struct file * filp){	PIPE_READERS(*inode)--;	PIPE_WRITERS(*inode)--;	wake_up_interruptible(&PIPE_WAIT(*inode));}/* * The file_operations structs are not static because they * are also used in linux/fs/fifo.c to do operations on fifo's. */struct file_operations connecting_fifo_fops = {	pipe_lseek,	connect_read,	bad_pipe_rw,	pipe_readdir,	connect_select,	pipe_ioctl,	NULL,		/* no mmap on pipes.. surprise */	NULL,		/* no special open code */	pipe_read_release,	NULL};struct file_operations read_fifo_fops = {	pipe_lseek,	pipe_read,	bad_pipe_rw,	pipe_readdir,	fifo_select,	pipe_ioctl,	NULL,		/* no mmap on pipes.. surprise */	NULL,		/* no special open code */	pipe_read_release,	NULL};struct file_operations write_fifo_fops = {	pipe_lseek,	bad_pipe_rw,	pipe_write,	pipe_readdir,	fifo_select,	pipe_ioctl,	NULL,		/* mmap */	NULL,		/* no special open code */	pipe_write_release,	NULL};struct file_operations rdwr_fifo_fops = {	pipe_lseek,	pipe_read,	pipe_write,	pipe_readdir,	fifo_select,	pipe_ioctl,	NULL,		/* mmap */	NULL,		/* no special open code */	pipe_rdwr_release,	NULL};struct file_operations read_pipe_fops = {	pipe_lseek,	pipe_read,	bad_pipe_rw,	pipe_readdir,	pipe_select,	pipe_ioctl,	NULL,		/* no mmap on pipes.. surprise */	NULL,		/* no special open code */	pipe_read_release,	NULL};struct file_operations write_pipe_fops = {	pipe_lseek,	bad_pipe_rw,	pipe_write,	pipe_readdir,	pipe_select,	pipe_ioctl,	NULL,		/* mmap */	NULL,		/* no special open code */	pipe_write_release,	NULL};struct file_operations rdwr_pipe_fops = {	pipe_lseek,	pipe_read,	pipe_write,	pipe_readdir,	pipe_select,	pipe_ioctl,	NULL,		/* mmap */	NULL,		/* no special open code */	pipe_rdwr_release,	NULL};struct inode_operations pipe_inode_operations = {	&rdwr_pipe_fops,	NULL,			/* create */	NULL,			/* lookup */	NULL,			/* link */	NULL,			/* unlink */	NULL,			/* symlink */	NULL,			/* mkdir */	NULL,			/* rmdir */	NULL,			/* mknod */	NULL,			/* rename */	NULL,			/* readlink */	NULL,			/* follow_link */	NULL,			/* bmap */	NULL,			/* truncate */	NULL			/* permission */};asmlinkage int sys_pipe(unsigned long * fildes){	struct inode * inode;	struct file * f[2];	int fd[2];	int i,j;	j = verify_area(VERIFY_WRITE,fildes,8);	if (j)		return j;	for(j=0 ; j<2 ; j++)		if (!(f[j] = get_empty_filp()))			break;	if (j==1)		f[0]->f_count--;	if (j<2)		return -ENFILE;	j=0;	for(i=0;j<2 && i<NR_OPEN;i++)		if (!current->filp[i]) {			current->filp[ fd[j]=i ] = f[j];			j++;		}	if (j==1)		current->filp[fd[0]]=NULL;	if (j<2) {		f[0]->f_count--;		f[1]->f_count--;		return -EMFILE;	}	if (!(inode=get_pipe_inode())) {		current->filp[fd[0]] = NULL;		current->filp[fd[1]] = NULL;		f[0]->f_count--;		f[1]->f_count--;		return -ENFILE;	}	f[0]->f_inode = f[1]->f_inode = inode;	f[0]->f_pos = f[1]->f_pos = 0;	f[0]->f_flags = O_RDONLY;	f[0]->f_op = &read_pipe_fops;	f[0]->f_mode = 1;		/* read */	f[1]->f_flags = O_WRONLY;	f[1]->f_op = &write_pipe_fops;	f[1]->f_mode = 2;		/* write */	put_fs_long(fd[0],0+fildes);	put_fs_long(fd[1],1+fildes);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -