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

📄 select.c

📁 minix3的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Implement entry point to select system call. * * The entry points into this file are *   do_select:	       perform the SELECT system call *   select_callback:  notify select system of possible fd operation  *   select_notified:  low-level entry for device notifying select *   select_unsuspend_by_proc: cancel a blocking select on exiting driver *  * Changes: *   6 june 2005  Created (Ben Gras) */#define DEBUG_SELECT 0#include "fs.h"#include "select.h"#include "file.h"#include "inode.h"#include <sys/time.h>#include <sys/select.h>#include <minix/com.h>#include <string.h>/* max. number of simultaneously pending select() calls */#define MAXSELECTS 25PRIVATE struct selectentry {	struct fproc *requestor;	/* slot is free iff this is NULL */	int req_procnr;	fd_set readfds, writefds, errorfds;	fd_set ready_readfds, ready_writefds, ready_errorfds;	fd_set *vir_readfds, *vir_writefds, *vir_errorfds;	struct filp *filps[FD_SETSIZE];	int type[FD_SETSIZE];	int nfds, nreadyfds;	clock_t expiry;	timer_t timer;	/* if expiry > 0 */} selecttab[MAXSELECTS];#define SELFD_FILE	0#define SELFD_PIPE	1#define SELFD_TTY	2#define SELFD_INET	3#define SELFD_LOG	4#define SEL_FDS		5FORWARD _PROTOTYPE(int select_reevaluate, (struct filp *fp));FORWARD _PROTOTYPE(int select_request_file,	 (struct filp *f, int *ops, int block));FORWARD _PROTOTYPE(int select_match_file, (struct filp *f));FORWARD _PROTOTYPE(int select_request_general,	 (struct filp *f, int *ops, int block));FORWARD _PROTOTYPE(int select_major_match,	(int match_major, struct filp *file));FORWARD _PROTOTYPE(void select_cancel_all, (struct selectentry *e));FORWARD _PROTOTYPE(void select_wakeup, (struct selectentry *e, int r));FORWARD _PROTOTYPE(void select_return, (struct selectentry *, int));/* The Open Group: * "The pselect() and select() functions shall support * regular files, terminal and pseudo-terminal devices, * STREAMS-based files, FIFOs, pipes, and sockets." */PRIVATE struct fdtype {	int (*select_request)(struct filp *, int *ops, int block);		int (*select_match)(struct filp *);	int select_major;} fdtypes[SEL_FDS] = {		/* SELFD_FILE */	{ select_request_file, select_match_file, 0 },		/* SELFD_TTY (also PTY) */	{ select_request_general, NULL, TTY_MAJOR },		/* SELFD_INET */	{ select_request_general, NULL, INET_MAJOR },		/* SELFD_PIPE (pipe(2) pipes and FS FIFOs) */	{ select_request_pipe, select_match_pipe, 0 },		/* SELFD_LOG (/dev/klog) */	{ select_request_general, NULL, LOG_MAJOR },};/* Open Group: * "File descriptors associated with regular files shall always select true * for ready to read, ready to write, and error conditions." *//*===========================================================================* *				select_request_file			     * *===========================================================================*/PRIVATE int select_request_file(struct filp *f, int *ops, int block){	/* output *ops is input *ops */	return SEL_OK;}/*===========================================================================* *				select_match_file			     * *===========================================================================*/PRIVATE int select_match_file(struct filp *file){	if (file && file->filp_ino && (file->filp_ino->i_mode & I_REGULAR))		return 1;	return 0;}/*===========================================================================* *				select_request_general			     * *===========================================================================*/PRIVATE int select_request_general(struct filp *f, int *ops, int block){	int rops = *ops;	if (block) rops |= SEL_NOTIFY;	*ops = dev_io(DEV_SELECT, f->filp_ino->i_zone[0], rops, NULL, 0, 0, 0);	if (*ops < 0)		return SEL_ERR;	return SEL_OK;}/*===========================================================================* *				select_major_match			     * *===========================================================================*/PRIVATE int select_major_match(int match_major, struct filp *file){	int major;	if (!(file && file->filp_ino &&		(file->filp_ino->i_mode & I_TYPE) == I_CHAR_SPECIAL))		return 0;	major = (file->filp_ino->i_zone[0] >> MAJOR) & BYTE;	if (major == match_major)		return 1;	return 0;}/*===========================================================================* *				tab2ops					     * *===========================================================================*/PRIVATE int tab2ops(int fd, struct selectentry *e){	return (FD_ISSET(fd, &e->readfds) ? SEL_RD : 0) |		(FD_ISSET(fd, &e->writefds) ? SEL_WR : 0) |		(FD_ISSET(fd, &e->errorfds) ? SEL_ERR : 0);}/*===========================================================================* *				ops2tab					     * *===========================================================================*/PRIVATE void ops2tab(int ops, int fd, struct selectentry *e){	if ((ops & SEL_RD) && e->vir_readfds && FD_ISSET(fd, &e->readfds)	        && !FD_ISSET(fd, &e->ready_readfds)) {		FD_SET(fd, &e->ready_readfds);		e->nreadyfds++;	}	if ((ops & SEL_WR) && e->vir_writefds && FD_ISSET(fd, &e->writefds) 		&& !FD_ISSET(fd, &e->ready_writefds)) {		FD_SET(fd, &e->ready_writefds);		e->nreadyfds++;	}	if ((ops & SEL_ERR) && e->vir_errorfds && FD_ISSET(fd, &e->errorfds)		&& !FD_ISSET(fd, &e->ready_errorfds)) {		FD_SET(fd, &e->ready_errorfds);		e->nreadyfds++;	}	return;}/*===========================================================================* *				copy_fdsets				     * *===========================================================================*/PRIVATE void copy_fdsets(struct selectentry *e){	if (e->vir_readfds)		sys_vircopy(SELF, D, (vir_bytes) &e->ready_readfds,		e->req_procnr, D, (vir_bytes) e->vir_readfds, sizeof(fd_set));	if (e->vir_writefds)		sys_vircopy(SELF, D, (vir_bytes) &e->ready_writefds,		e->req_procnr, D, (vir_bytes) e->vir_writefds, sizeof(fd_set));	if (e->vir_errorfds)		sys_vircopy(SELF, D, (vir_bytes) &e->ready_errorfds,		e->req_procnr, D, (vir_bytes) e->vir_errorfds, sizeof(fd_set));	return;}/*===========================================================================* *				do_select				      * *===========================================================================*/PUBLIC int do_select(void){	int r, nfds, is_timeout = 1, nonzero_timeout = 0,		fd, s, block = 0;	struct timeval timeout;	nfds = m_in.SEL_NFDS;	if (nfds < 0 || nfds > FD_SETSIZE)		return EINVAL;	for(s = 0; s < MAXSELECTS; s++)		if (!selecttab[s].requestor)			break;	if (s >= MAXSELECTS)		return ENOSPC;	selecttab[s].req_procnr = who;	selecttab[s].nfds = 0;	selecttab[s].nreadyfds = 0;	memset(selecttab[s].filps, 0, sizeof(selecttab[s].filps));	/* defaults */	FD_ZERO(&selecttab[s].readfds);	FD_ZERO(&selecttab[s].writefds);	FD_ZERO(&selecttab[s].errorfds);	FD_ZERO(&selecttab[s].ready_readfds);	FD_ZERO(&selecttab[s].ready_writefds);	FD_ZERO(&selecttab[s].ready_errorfds);	selecttab[s].vir_readfds = (fd_set *) m_in.SEL_READFDS;	selecttab[s].vir_writefds = (fd_set *) m_in.SEL_WRITEFDS;	selecttab[s].vir_errorfds = (fd_set *) m_in.SEL_ERRORFDS;	/* copy args */	if (selecttab[s].vir_readfds	 && (r=sys_vircopy(who, D, (vir_bytes) m_in.SEL_READFDS,		SELF, D, (vir_bytes) &selecttab[s].readfds, sizeof(fd_set))) != OK)		return r;	if (selecttab[s].vir_writefds	 && (r=sys_vircopy(who, D, (vir_bytes) m_in.SEL_WRITEFDS,		SELF, D, (vir_bytes) &selecttab[s].writefds, sizeof(fd_set))) != OK)		return r;	if (selecttab[s].vir_errorfds	 && (r=sys_vircopy(who, D, (vir_bytes) m_in.SEL_ERRORFDS,		SELF, D, (vir_bytes) &selecttab[s].errorfds, sizeof(fd_set))) != OK)		return r;	if (!m_in.SEL_TIMEOUT)		is_timeout = nonzero_timeout = 0;	else		if ((r=sys_vircopy(who, D, (vir_bytes) m_in.SEL_TIMEOUT,			SELF, D, (vir_bytes) &timeout, sizeof(timeout))) != OK)			return r;	/* No nonsense in the timeval please. */	if (is_timeout && (timeout.tv_sec < 0 || timeout.tv_usec < 0))		return EINVAL;	/* if is_timeout if 0, we block forever. otherwise, if nonzero_timeout	 * is 0, we do a poll (don't block). otherwise, we block up to the	 * specified time interval.	 */	if (is_timeout && (timeout.tv_sec > 0 || timeout.tv_usec > 0))		nonzero_timeout = 1;	if (nonzero_timeout || !is_timeout)		block = 1;	else		block = 0; /* timeout set as (0,0) - this effects a poll */	/* no timeout set (yet) */	selecttab[s].expiry = 0;	for(fd = 0; fd < nfds; fd++) {		int orig_ops, ops, t, type = -1, r;		struct filp *filp;			if (!(orig_ops = ops = tab2ops(fd, &selecttab[s])))			continue;		if (!(filp = selecttab[s].filps[fd] = get_filp(fd))) {			select_cancel_all(&selecttab[s]);			return EBADF;		}		for(t = 0; t < SEL_FDS; t++) {			if (fdtypes[t].select_match) {			   if (fdtypes[t].select_match(filp)) {#if DEBUG_SELECT				printf("select: fd %d is type %d ", fd, t);#endif				if (type != -1)					printf("select: double match\n");				type = t;			  }	 		} else if (select_major_match(fdtypes[t].select_major, filp)) {				type = t;			}		}		/* Open Group:		 * "The pselect() and select() functions shall support		 * regular files, terminal and pseudo-terminal devices,		 * STREAMS-based files, FIFOs, pipes, and sockets. The		 * behavior of pselect() and select() on file descriptors		 * that refer to other types of file is unspecified."		 *		 * If all types are implemented, then this is another		 * type of file and we get to do whatever we want.		 */		if (type == -1)		{#if DEBUG_SELECT			printf("do_select: bad type\n");#endif			return EBADF;		}		selecttab[s].type[fd] = type;		if ((selecttab[s].filps[fd]->filp_select_ops & ops) != ops) {			int wantops;			/* Request the select on this fd.  */#if DEBUG_SELECT			printf("%p requesting ops %d -> ",				selecttab[s].filps[fd],				selecttab[s].filps[fd]->filp_select_ops);#endif			wantops = (selecttab[s].filps[fd]->filp_select_ops |= ops);#if DEBUG_SELECT			printf("%d\n", selecttab[s].filps[fd]->filp_select_ops);#endif			if ((r = fdtypes[type].select_request(filp,				&wantops, block)) != SEL_OK) {				/* error or bogus return code.. backpaddle */				select_cancel_all(&selecttab[s]);				printf("select: select_request returned error\n");				return EINVAL;			}			if (wantops) {				if (wantops & ops) {					/* operations that were just requested					 * are ready to go right away					 */					ops2tab(wantops, fd, &selecttab[s]);				}				/* if there are any other select()s blocking				 * on these operations of this fp, they can				 * be awoken too				 */				select_callback(filp, ops);			}#if DEBUG_SELECT			printf("select request ok; ops returned %d\n", wantops);#endif		} else {#if DEBUG_SELECT			printf("select already happening on that filp\n");

⌨️ 快捷键说明

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