亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? pipe.c

?? Linux設備驅動的經典教材, 該電子書是第三版,并附有全部配套代碼.
?? C
字號:
/* * pipe.c -- fifo driver for scull * * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet * Copyright (C) 2001 O'Reilly & Associates * * The source code in this file can be freely used, adapted, * and redistributed in source or binary form, so long as an * acknowledgment appears in derived source files.  The citation * should list that the code comes from the book "Linux Device * Drivers" by Alessandro Rubini and Jonathan Corbet, published * by O'Reilly & Associates.   No warranty is attached; * we cannot take responsibility for errors or fitness for use. * */ #include <linux/module.h>#include <linux/moduleparam.h>#include <linux/kernel.h>	/* printk(), min() */#include <linux/slab.h>		/* kmalloc() */#include <linux/fs.h>		/* everything... */#include <linux/proc_fs.h>#include <linux/errno.h>	/* error codes */#include <linux/types.h>	/* size_t */#include <linux/fcntl.h>#include <linux/poll.h>#include <linux/cdev.h>#include <asm/uaccess.h>#include "scull.h"		/* local definitions */struct scull_pipe {        wait_queue_head_t inq, outq;       /* read and write queues */        char *buffer, *end;                /* begin of buf, end of buf */        int buffersize;                    /* used in pointer arithmetic */        char *rp, *wp;                     /* where to read, where to write */        int nreaders, nwriters;            /* number of openings for r/w */        struct fasync_struct *async_queue; /* asynchronous readers */        struct semaphore sem;              /* mutual exclusion semaphore */        struct cdev cdev;                  /* Char device structure */};/* parameters */static int scull_p_nr_devs = SCULL_P_NR_DEVS;	/* number of pipe devices */int scull_p_buffer =  SCULL_P_BUFFER;	/* buffer size */dev_t scull_p_devno;			/* Our first device number */module_param(scull_p_nr_devs, int, 0);	/* FIXME check perms */module_param(scull_p_buffer, int, 0);static struct scull_pipe *scull_p_devices;static int scull_p_fasync(int fd, struct file *filp, int mode);static int spacefree(struct scull_pipe *dev);/* * Open and close */static int scull_p_open(struct inode *inode, struct file *filp){	struct scull_pipe *dev;	dev = container_of(inode->i_cdev, struct scull_pipe, cdev);	filp->private_data = dev;	if (down_interruptible(&dev->sem))		return -ERESTARTSYS;	if (!dev->buffer) {		/* allocate the buffer */		dev->buffer = kmalloc(scull_p_buffer, GFP_KERNEL);		if (!dev->buffer) {			up(&dev->sem);			return -ENOMEM;		}	}	dev->buffersize = scull_p_buffer;	dev->end = dev->buffer + dev->buffersize;	dev->rp = dev->wp = dev->buffer; /* rd and wr from the beginning */	/* use f_mode,not  f_flags: it's cleaner (fs/open.c tells why) */	if (filp->f_mode & FMODE_READ)		dev->nreaders++;	if (filp->f_mode & FMODE_WRITE)		dev->nwriters++;	up(&dev->sem);	return nonseekable_open(inode, filp);}static int scull_p_release(struct inode *inode, struct file *filp){	struct scull_pipe *dev = filp->private_data;	/* remove this filp from the asynchronously notified filp's */	scull_p_fasync(-1, filp, 0);	down(&dev->sem);	if (filp->f_mode & FMODE_READ)		dev->nreaders--;	if (filp->f_mode & FMODE_WRITE)		dev->nwriters--;	if (dev->nreaders + dev->nwriters == 0) {		kfree(dev->buffer);		dev->buffer = NULL; /* the other fields are not checked on open */	}	up(&dev->sem);	return 0;}/* * Data management: read and write */static ssize_t scull_p_read (struct file *filp, char __user *buf, size_t count,                loff_t *f_pos){	struct scull_pipe *dev = filp->private_data;	if (down_interruptible(&dev->sem))		return -ERESTARTSYS;	while (dev->rp == dev->wp) { /* nothing to read */		up(&dev->sem); /* release the lock */		if (filp->f_flags & O_NONBLOCK)			return -EAGAIN;		PDEBUG("\"%s\" reading: going to sleep\n", current->comm);		if (wait_event_interruptible(dev->inq, (dev->rp != dev->wp)))			return -ERESTARTSYS; /* signal: tell the fs layer to handle it */		/* otherwise loop, but first reacquire the lock */		if (down_interruptible(&dev->sem))			return -ERESTARTSYS;	}	/* ok, data is there, return something */	if (dev->wp > dev->rp)		count = min(count, (size_t)(dev->wp - dev->rp));	else /* the write pointer has wrapped, return data up to dev->end */		count = min(count, (size_t)(dev->end - dev->rp));	if (copy_to_user(buf, dev->rp, count)) {		up (&dev->sem);		return -EFAULT;	}	dev->rp += count;	if (dev->rp == dev->end)		dev->rp = dev->buffer; /* wrapped */	up (&dev->sem);	/* finally, awake any writers and return */	wake_up_interruptible(&dev->outq);	PDEBUG("\"%s\" did read %li bytes\n",current->comm, (long)count);	return count;}/* Wait for space for writing; caller must hold device semaphore.  On * error the semaphore will be released before returning. */static int scull_getwritespace(struct scull_pipe *dev, struct file *filp){	while (spacefree(dev) == 0) { /* full */		DEFINE_WAIT(wait);				up(&dev->sem);		if (filp->f_flags & O_NONBLOCK)			return -EAGAIN;		PDEBUG("\"%s\" writing: going to sleep\n",current->comm);		prepare_to_wait(&dev->outq, &wait, TASK_INTERRUPTIBLE);		if (spacefree(dev) == 0)			schedule();		finish_wait(&dev->outq, &wait);		if (signal_pending(current))			return -ERESTARTSYS; /* signal: tell the fs layer to handle it */		if (down_interruptible(&dev->sem))			return -ERESTARTSYS;	}	return 0;}	/* How much space is free? */static int spacefree(struct scull_pipe *dev){	if (dev->rp == dev->wp)		return dev->buffersize - 1;	return ((dev->rp + dev->buffersize - dev->wp) % dev->buffersize) - 1;}static ssize_t scull_p_write(struct file *filp, const char __user *buf, size_t count,                loff_t *f_pos){	struct scull_pipe *dev = filp->private_data;	int result;	if (down_interruptible(&dev->sem))		return -ERESTARTSYS;	/* Make sure there's space to write */	result = scull_getwritespace(dev, filp);	if (result)		return result; /* scull_getwritespace called up(&dev->sem) */	/* ok, space is there, accept something */	count = min(count, (size_t)spacefree(dev));	if (dev->wp >= dev->rp)		count = min(count, (size_t)(dev->end - dev->wp)); /* to end-of-buf */	else /* the write pointer has wrapped, fill up to rp-1 */		count = min(count, (size_t)(dev->rp - dev->wp - 1));	PDEBUG("Going to accept %li bytes to %p from %p\n", (long)count, dev->wp, buf);	if (copy_from_user(dev->wp, buf, count)) {		up (&dev->sem);		return -EFAULT;	}	dev->wp += count;	if (dev->wp == dev->end)		dev->wp = dev->buffer; /* wrapped */	up(&dev->sem);	/* finally, awake any reader */	wake_up_interruptible(&dev->inq);  /* blocked in read() and select() */	/* and signal asynchronous readers, explained late in chapter 5 */	if (dev->async_queue)		kill_fasync(&dev->async_queue, SIGIO, POLL_IN);	PDEBUG("\"%s\" did write %li bytes\n",current->comm, (long)count);	return count;}static unsigned int scull_p_poll(struct file *filp, poll_table *wait){	struct scull_pipe *dev = filp->private_data;	unsigned int mask = 0;	/*	 * The buffer is circular; it is considered full	 * if "wp" is right behind "rp" and empty if the	 * two are equal.	 */	down(&dev->sem);	poll_wait(filp, &dev->inq,  wait);	poll_wait(filp, &dev->outq, wait);	if (dev->rp != dev->wp)		mask |= POLLIN | POLLRDNORM;	/* readable */	if (spacefree(dev))		mask |= POLLOUT | POLLWRNORM;	/* writable */	up(&dev->sem);	return mask;}static int scull_p_fasync(int fd, struct file *filp, int mode){	struct scull_pipe *dev = filp->private_data;	return fasync_helper(fd, filp, mode, &dev->async_queue);}/* FIXME this should use seq_file */#ifdef SCULL_DEBUGstatic void scullp_proc_offset(char *buf, char **start, off_t *offset, int *len){	if (*offset == 0)		return;	if (*offset >= *len) {	/* Not there yet */		*offset -= *len;		*len = 0;	}	else {			/* We're into the interesting stuff now */		*start = buf + *offset;		*offset = 0;	}}static int scull_read_p_mem(char *buf, char **start, off_t offset, int count,		int *eof, void *data){	int i, len;	struct scull_pipe *p;#define LIMIT (PAGE_SIZE-200)	/* don't print any more after this size */	*start = buf;	len = sprintf(buf, "Default buffersize is %i\n", scull_p_buffer);	for(i = 0; i<scull_p_nr_devs && len <= LIMIT; i++) {		p = &scull_p_devices[i];		if (down_interruptible(&p->sem))			return -ERESTARTSYS;		len += sprintf(buf+len, "\nDevice %i: %p\n", i, p);/*		len += sprintf(buf+len, "   Queues: %p %p\n", p->inq, p->outq);*/		len += sprintf(buf+len, "   Buffer: %p to %p (%i bytes)\n", p->buffer, p->end, p->buffersize);		len += sprintf(buf+len, "   rp %p   wp %p\n", p->rp, p->wp);		len += sprintf(buf+len, "   readers %i   writers %i\n", p->nreaders, p->nwriters);		up(&p->sem);		scullp_proc_offset(buf, start, &offset, &len);	}	*eof = (len <= LIMIT);	return len;}#endif/* * The file operations for the pipe device * (some are overlayed with bare scull) */struct file_operations scull_pipe_fops = {	.owner =	THIS_MODULE,	.llseek =	no_llseek,	.read =		scull_p_read,	.write =	scull_p_write,	.poll =		scull_p_poll,	.ioctl =	scull_ioctl,	.open =		scull_p_open,	.release =	scull_p_release,	.fasync =	scull_p_fasync,};/* * Set up a cdev entry. */static void scull_p_setup_cdev(struct scull_pipe *dev, int index){	int err, devno = scull_p_devno + index;    	cdev_init(&dev->cdev, &scull_pipe_fops);	dev->cdev.owner = THIS_MODULE;	err = cdev_add (&dev->cdev, devno, 1);	/* Fail gracefully if need be */	if (err)		printk(KERN_NOTICE "Error %d adding scullpipe%d", err, index);} /* * Initialize the pipe devs; return how many we did. */int scull_p_init(dev_t firstdev){	int i, result;	result = register_chrdev_region(firstdev, scull_p_nr_devs, "scullp");	if (result < 0) {		printk(KERN_NOTICE "Unable to get scullp region, error %d\n", result);		return 0;	}	scull_p_devno = firstdev;	scull_p_devices = kmalloc(scull_p_nr_devs * sizeof(struct scull_pipe), GFP_KERNEL);	if (scull_p_devices == NULL) {		unregister_chrdev_region(firstdev, scull_p_nr_devs);		return 0;	}	memset(scull_p_devices, 0, scull_p_nr_devs * sizeof(struct scull_pipe));	for (i = 0; i < scull_p_nr_devs; i++) {		init_waitqueue_head(&(scull_p_devices[i].inq));		init_waitqueue_head(&(scull_p_devices[i].outq));		init_MUTEX(&scull_p_devices[i].sem);		scull_p_setup_cdev(scull_p_devices + i, i);	}#ifdef SCULL_DEBUG	create_proc_read_entry("scullpipe", 0, NULL, scull_read_p_mem, NULL);#endif	return scull_p_nr_devs;}/* * This is called by cleanup_module or on failure. * It is required to never fail, even if nothing was initialized first */void scull_p_cleanup(void){	int i;#ifdef SCULL_DEBUG	remove_proc_entry("scullpipe", NULL);#endif	if (!scull_p_devices)		return; /* nothing else to release */	for (i = 0; i < scull_p_nr_devs; i++) {		cdev_del(&scull_p_devices[i].cdev);		kfree(scull_p_devices[i].buffer);	}	kfree(scull_p_devices);	unregister_chrdev_region(scull_p_devno, scull_p_nr_devs);	scull_p_devices = NULL; /* pedantic */}

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
欧美影院一区二区三区| 成人高清免费观看| 一区二区三区高清| 成人欧美一区二区三区黑人麻豆| 久久综合九色综合欧美就去吻| 69成人精品免费视频| 91精品国产麻豆国产自产在线| 91成人看片片| 欧美日韩亚洲另类| 91精品国产综合久久蜜臀 | 精品久久久久久久久久久久久久久久久| 91久久精品网| 91精品一区二区三区在线观看| 欧美精品一二三四| 日韩免费福利电影在线观看| 日韩一区二区电影网| 欧美精品一区二区三区四区 | 国产欧美精品一区二区色综合| 日韩欧美国产麻豆| 欧美精品一区在线观看| 国产亚洲精品超碰| 1024精品合集| 亚洲小少妇裸体bbw| 轻轻草成人在线| 国产麻豆成人精品| 99精品一区二区| 欧美日韩国产小视频在线观看| 91精品国产欧美一区二区| 久久色.com| 亚洲免费伊人电影| 免费成人你懂的| 99re亚洲国产精品| 欧美精品视频www在线观看| 精品少妇一区二区三区在线播放 | 欧美精品一区二区三区视频| 久久久久久久久久看片| 一区二区三区四区视频精品免费| 亚洲影视在线观看| 精东粉嫩av免费一区二区三区| 懂色av一区二区三区免费看| 精品视频资源站| 欧美激情一区在线观看| 亚洲资源在线观看| 国产成人精品影院| 91.成人天堂一区| 日本一区二区三区四区在线视频 | 欧美日韩国产首页在线观看| 26uuu欧美| 午夜av电影一区| jlzzjlzz亚洲日本少妇| 日韩欧美在线影院| 一区二区三区av电影| 国产一区二三区| 欧美亚洲尤物久久| 自拍偷拍国产精品| 国产又粗又猛又爽又黄91精品| 在线一区二区三区四区五区 | 91国偷自产一区二区三区成为亚洲经典 | 精品国产乱码久久久久久浪潮| 日韩一区中文字幕| 国产aⅴ综合色| 日韩免费在线观看| 亚洲v日本v欧美v久久精品| 成人美女视频在线看| 精品国产一区二区在线观看| 亚洲自拍与偷拍| 色婷婷亚洲婷婷| 国产精品拍天天在线| 奇米精品一区二区三区在线观看 | 精品精品国产高清a毛片牛牛| 一区二区三区波多野结衣在线观看| 丰满放荡岳乱妇91ww| 久久久久国产一区二区三区四区 | 中文字幕的久久| 韩国av一区二区| 精品久久久久香蕉网| 久久精品国产成人一区二区三区| 欧美喷潮久久久xxxxx| 亚洲午夜久久久久久久久久久| 色综合婷婷久久| 亚洲黄色尤物视频| 欧美午夜宅男影院| 亚洲一二三四区| 欧美日韩日日骚| 日韩国产一区二| 日韩午夜电影在线观看| 久久99深爱久久99精品| 亚洲精品一区二区三区在线观看 | 不卡电影免费在线播放一区| 欧美激情在线一区二区三区| 91丨porny丨国产| 一区二区免费视频| 日韩视频一区在线观看| 久久99精品国产| 国产日韩v精品一区二区| av亚洲精华国产精华精华| 国产精品成人免费| 欧美日韩国产在线播放网站| 久久精品国产999大香线蕉| 久久精品人人做人人爽人人 | 亚洲最大成人网4388xx| 欧洲中文字幕精品| 久久国产成人午夜av影院| 久久久精品欧美丰满| 在线亚洲一区二区| 蜜芽一区二区三区| 欧美国产日韩精品免费观看| 欧美影视一区在线| 久88久久88久久久| 伊人婷婷欧美激情| 国产女人18毛片水真多成人如厕| 成人午夜激情影院| 视频一区二区不卡| 亚洲国产激情av| 91精品国产综合久久精品app| 国产一区福利在线| 亚洲成人高清在线| 国产日韩精品一区二区三区在线| 欧美视频第二页| 福利电影一区二区| 奇米精品一区二区三区在线观看| 国产精品久久久久久户外露出| 欧美一区二区三级| 色综合视频一区二区三区高清| 国产自产2019最新不卡| 一级做a爱片久久| 亚洲国产精品传媒在线观看| 欧美久久久久中文字幕| 色婷婷综合久久久久中文| 国产酒店精品激情| 免费观看久久久4p| 亚洲国产va精品久久久不卡综合| 国产三级精品在线| 精品国产麻豆免费人成网站| 91精彩视频在线| 97精品国产露脸对白| 国产一区二区不卡| 精品一区二区国语对白| 亚洲国产成人精品视频| 亚洲日本在线观看| 久久精品视频一区二区| 久久中文字幕电影| 精品乱人伦小说| 日韩亚洲电影在线| 欧美一二区视频| 91精品国产色综合久久不卡电影| 在线观看成人免费视频| 色视频成人在线观看免| 成人动漫精品一区二区| 成人av在线看| 国产成人精品影视| 成人中文字幕合集| youjizz久久| 91亚洲精品乱码久久久久久蜜桃| 国产精品自拍三区| 国产黄色精品视频| 国产成人免费网站| 国产精品18久久久| 成人免费视频国产在线观看| 国产99久久久国产精品免费看| 久久99精品网久久| 国产福利电影一区二区三区| 国产一区二区伦理| 国产精品综合视频| av在线播放不卡| 欧美最新大片在线看| 欧美日韩精品欧美日韩精品| 欧美人狂配大交3d怪物一区| 91精品国产综合久久婷婷香蕉| 日韩亚洲欧美成人一区| 久久这里都是精品| 国产精品黄色在线观看| 一区二区成人在线观看| 视频在线观看91| 美国一区二区三区在线播放| 国产传媒欧美日韩成人| 91在线观看下载| 欧美日韩在线播放| 欧美v国产在线一区二区三区| 国产农村妇女毛片精品久久麻豆| 国产精品不卡在线| 舔着乳尖日韩一区| 国产在线精品不卡| 91黄色免费看| 337p粉嫩大胆色噜噜噜噜亚洲| 一区二区中文视频| 日本麻豆一区二区三区视频| 粉嫩一区二区三区在线看 | 麻豆精品视频在线| 成人av综合在线| 欧美精品第一页| 国产欧美精品一区aⅴ影院| 亚洲一区二区精品久久av| 蜜臀av性久久久久蜜臀aⅴ流畅| 成人免费av网站| 日韩欧美中文字幕精品| 亚洲精品视频在线观看免费| 麻豆精品国产传媒mv男同| 91亚洲男人天堂| 久久久久久久综合色一本|