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

📄 pipe.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 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>#include <linux/mm.h>/* * Define this if you want SunOS compatibility wrt braindead * select behaviour on FIFO's. */#undef FIFO_SUNOS_BRAINDAMAGE/* We don't use the head/tail construction any more. Now we use the start/len*//* construction 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) {		UPDATE_ATIME(inode);		return read;	}	if (PIPE_WRITERS(*inode))		return -EAGAIN;	return 0;}	static int pipe_write(struct inode * inode, struct file * filp, const 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;	}	inode->i_ctime = inode->i_mtime = CURRENT_TIME;	return written;}static int pipe_lseek(struct inode * inode, struct file * file, off_t offset, int orig){	return -ESPIPE;}static int bad_pipe_r(struct inode * inode, struct file * filp, char * buf, int count){	return -EBADF;}static int bad_pipe_w(struct inode * inode, struct file * filp, const 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, sizeof(int));			if (!error)				put_user(PIPE_SIZE(*pino),(int *) 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_EMPTY(*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;}#ifdef FIFO_SUNOS_BRAINDAMAGE/* * 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;}#else#define fifo_select pipe_select#endif /* FIFO_SUNOS_BRAINDAMAGE *//* * 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){	if (PIPE_EMPTY(*inode) && !PIPE_WRITERS(*inode))		return 0;	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;			}			if (PIPE_WRITERS(*inode)) {				filp->f_op = &read_fifo_fops;			}			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;}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){	if (filp->f_mode & FMODE_READ)		PIPE_READERS(*inode)--;	if (filp->f_mode & FMODE_WRITE)		PIPE_WRITERS(*inode)--;	wake_up_interruptible(&PIPE_WAIT(*inode));}static int pipe_read_open(struct inode * inode, struct file * filp){	PIPE_READERS(*inode)++;	return 0;}static int pipe_write_open(struct inode * inode, struct file * filp){	PIPE_WRITERS(*inode)++;	return 0;}static int pipe_rdwr_open(struct inode * inode, struct file * filp){	if (filp->f_mode & FMODE_READ)		PIPE_READERS(*inode)++;	if (filp->f_mode & FMODE_WRITE)		PIPE_WRITERS(*inode)++;	return 0;}/* * 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_w,	NULL,		/* no readdir */	connect_select,	pipe_ioctl,	NULL,		/* no mmap on pipes.. surprise */	pipe_read_open,	pipe_read_release,	NULL};struct file_operations read_fifo_fops = {	pipe_lseek,	pipe_read,	bad_pipe_w,	NULL,		/* no readdir */	fifo_select,	pipe_ioctl,	NULL,		/* no mmap on pipes.. surprise */	pipe_read_open,	pipe_read_release,	NULL};struct file_operations write_fifo_fops = {	pipe_lseek,	bad_pipe_r,	pipe_write,	NULL,		/* no readdir */	fifo_select,	pipe_ioctl,	NULL,		/* mmap */	pipe_write_open,	pipe_write_release,	NULL};struct file_operations rdwr_fifo_fops = {	pipe_lseek,	pipe_read,	pipe_write,	NULL,		/* no readdir */	fifo_select,	pipe_ioctl,	NULL,		/* mmap */	pipe_rdwr_open,	pipe_rdwr_release,	NULL};struct file_operations read_pipe_fops = {	pipe_lseek,	pipe_read,	bad_pipe_w,	NULL,		/* no readdir */	pipe_select,	pipe_ioctl,	NULL,		/* no mmap on pipes.. surprise */	pipe_read_open,	pipe_read_release,	NULL};struct file_operations write_pipe_fops = {	pipe_lseek,	bad_pipe_r,	pipe_write,	NULL,		/* no readdir */	pipe_select,	pipe_ioctl,	NULL,		/* mmap */	pipe_write_open,	pipe_write_release,	NULL};struct file_operations rdwr_pipe_fops = {	pipe_lseek,	pipe_read,	pipe_write,	NULL,		/* no readdir */	pipe_select,	pipe_ioctl,	NULL,		/* mmap */	pipe_rdwr_open,	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,			/* readpage */	NULL,			/* writepage */	NULL,			/* bmap */	NULL,			/* truncate */	NULL			/* permission */};int do_pipe(int *fd){	struct inode * inode;	struct file *f1, *f2;	int error;	int i,j;	error = ENFILE;	f1 = get_empty_filp();	if (!f1)		goto no_files;	f2 = get_empty_filp();	if (!f2)		goto close_f1;	inode = get_pipe_inode();	if (!inode)		goto close_f12;	error = get_unused_fd();	if (error < 0)		goto close_f12_inode;	i = error;	error = get_unused_fd();	if (error < 0)		goto close_f12_inode_i;	j = error;	f1->f_inode = f2->f_inode = inode;	/* read file */	f1->f_pos = f2->f_pos = 0;	f1->f_flags = O_RDONLY;	f1->f_op = &read_pipe_fops;	f1->f_mode = 1;	/* write file */	f2->f_flags = O_WRONLY;	f2->f_op = &write_pipe_fops;	f2->f_mode = 2;	current->files->fd[i] = f1;	current->files->fd[j] = f2;	fd[0] = i;	fd[1] = j;	return 0;close_f12_inode_i:	put_unused_fd(i);close_f12_inode:	inode->i_count--;	iput(inode);close_f12:	f2->f_count--;close_f1:	f1->f_count--;no_files:	return error;	}

⌨️ 快捷键说明

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