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

📄 device.c

📁 一个简单的操作系统minix的核心代码
💻 C
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
				src/fs/device.c	 	 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

27000	/* When a needed block is not in the cache, it must be fetched from the disk.
27001	 * Special character files also require I/O.  The routines for these are here.
27002	 *
27003	 * The entry points in this file are:
27004	 *   dev_io:     perform a read or write on a block or character device
27005	 *   dev_opcl:   perform generic device-specific processing for open & close
27006	 *   tty_open:   perform tty-specific processing for open
27007	 *   ctty_open:  perform controlling-tty-specific processing for open
27008	 *   ctty_close: perform controlling-tty-specific processing for close
27009	 *   do_setsid:  perform the SETSID system call (FS side)
27010	 *   do_ioctl:   perform the IOCTL system call
27011	 *   call_task:  procedure that actually calls the kernel tasks
27012	 *   call_ctty:  procedure that actually calls task for /dev/tty
27013	 */
27014	
27015	#include "fs.h"
27016	#include <fcntl.h>
27017	#include <minix/callnr.h>
27018	#include <minix/com.h>
27019	#include "dev.h"
27020	#include "file.h"
27021	#include "fproc.h"
27022	#include "inode.h"
27023	#include "param.h"
27024	
27025	PRIVATE message dev_mess;
27026	PRIVATE major, minor, task;
27027	
27028	FORWARD _PROTOTYPE( void find_dev, (Dev_t dev)                          );
27029	
27030	/*===========================================================================*
27031	 *                              dev_io                                       *
27032	 *===========================================================================*/
27033	PUBLIC int dev_io(op, nonblock, dev, pos, bytes, proc, buff)
27034	int op;                         /* DEV_READ, DEV_WRITE, DEV_IOCTL, etc. */
27035	int nonblock;                   /* TRUE if nonblocking op */
27036	dev_t dev;                      /* major-minor device number */
27037	off_t pos;                      /* byte position */
27038	int bytes;                      /* how many bytes to transfer */
27039	int proc;                       /* in whose address space is buff? */
27040	char *buff;                     /* virtual address of the buffer */
27041	{
27042	/* Read or write from a device.  The parameter 'dev' tells which one. */
27043	
27044	  find_dev(dev);                /* load the variables major, minor, and task */
27045	
27046	  /* Set up the message passed to task. */
27047	  dev_mess.m_type   = op;
27048	  dev_mess.DEVICE   = (dev >> MINOR) & BYTE;
27049	  dev_mess.POSITION = pos;
27050	  dev_mess.PROC_NR  = proc;
27051	  dev_mess.ADDRESS  = buff;
27052	  dev_mess.COUNT    = bytes;
27053	  dev_mess.TTY_FLAGS = nonblock; /* temporary kludge */
27054	
27055	  /* Call the task. */
27056	  (*dmap[major].dmap_rw)(task, &dev_mess);
27057	
27058	  /* Task has completed.  See if call completed. */
27059	  if (dev_mess.REP_STATUS == SUSPEND) {
27060	        if (op == DEV_OPEN) task = XPOPEN;
27061	        suspend(task);          /* suspend user */
27062	  }
27063	
27064	  return(dev_mess.REP_STATUS);
27065	}
	
	
27068	/*===========================================================================*
27069	 *                              dev_opcl                                     *
27070	 *===========================================================================*/
27071	PUBLIC void dev_opcl(task_nr, mess_ptr)
27072	int task_nr;                    /* which task */
27073	message *mess_ptr;              /* message pointer */
27074	{
27075	/* Called from the dmap struct in table.c on opens & closes of special files.*/
27076	
27077	  int op;
27078	
27079	  op = mess_ptr->m_type;        /* save DEV_OPEN or DEV_CLOSE for later */
27080	  mess_ptr->DEVICE = (mess_ptr->DEVICE >> MINOR) & BYTE;
27081	  mess_ptr->PROC_NR = fp - fproc;
27082	
27083	  call_task(task_nr, mess_ptr);
27084	
27085	  /* Task has completed.  See if call completed. */
27086	  if (mess_ptr->REP_STATUS == SUSPEND) {
27087	        if (op == DEV_OPEN) task_nr = XPOPEN;
27088	        suspend(task_nr);       /* suspend user */
27089	  }
27090	}
	
27092	/*===========================================================================*
27093	 *                              tty_open                                     *
27094	 *===========================================================================*/
27095	PUBLIC void tty_open(task_nr, mess_ptr)
27096	int task_nr;
27097	message *mess_ptr;
27098	{
27099	/* This procedure is called from the dmap struct in table.c on tty opens. */
27100	  
27101	  int r;
27102	  dev_t dev;
27103	  int flags, proc;
27104	  register struct fproc *rfp;
27105	
27106	  dev = (dev_t) mess_ptr->DEVICE;
27107	  flags = mess_ptr->COUNT;
27108	  proc = fp - fproc;
27109	
27110	  /* Add O_NOCTTY to the flags if this process is not a session leader, or
27111	   * if it already has a controlling tty, or if it is someone elses
27112	   * controlling tty.
27113	   */
27114	  if (!fp->fp_sesldr || fp->fp_tty != 0) {
27115	        flags |= O_NOCTTY;
27116	  } else {
27117	        for (rfp = &fproc[LOW_USER]; rfp < &fproc[NR_PROCS]; rfp++) {
27118	                if (rfp->fp_tty == dev) flags |= O_NOCTTY;
27119	        }
27120	  }
27121	
27122	  r = dev_io(DEV_OPEN, mode, dev, (off_t) 0, flags, proc, NIL_PTR);
27123	
27124	  if (r == 1) {
27125	        fp->fp_tty = dev;
27126	        r = OK;
27127	  }
27128	
27129	  mess_ptr->REP_STATUS = r;
27130	}
	
	
27133	/*===========================================================================*
27134	 *                              ctty_open                                    *
27135	 *===========================================================================*/
27136	PUBLIC void ctty_open(task_nr, mess_ptr)
27137	int task_nr;
27138	message *mess_ptr;
27139	{
27140	/* This procedure is called from the dmap struct in table.c on opening
27141	 * /dev/tty, the magic device that translates to the controlling tty.
27142	 */
27143	  
27144	  mess_ptr->REP_STATUS = fp->fp_tty == 0 ? ENXIO : OK;
27145	}
	
	
27148	/*===========================================================================*
27149	 *                              ctty_close                                   *
27150	 *===========================================================================*/
27151	PUBLIC void ctty_close(task_nr, mess_ptr)
27152	int task_nr;
27153	message *mess_ptr;
27154	{
27155	/* Close /dev/tty. */
27156	
27157	  mess_ptr->REP_STATUS = OK;
27158	}
	
	
27161	/*===========================================================================*
27162	 *                              do_setsid                                    *
27163	 *===========================================================================*/
27164	PUBLIC int do_setsid()
27165	{
27166	/* Perform the FS side of the SETSID call, i.e. get rid of the controlling
27167	 * terminal of a process, and make the process a session leader.
27168	 */
27169	  register struct fproc *rfp;
27170	
27171	  /* Only MM may do the SETSID call directly. */
27172	  if (who != MM_PROC_NR) return(ENOSYS);
27173	
27174	  /* Make the process a session leader with no controlling tty. */
27175	  rfp = &fproc[slot1];
27176	  rfp->fp_sesldr = TRUE;
27177	  rfp->fp_tty = 0;
27178	}
	
	
27181	/*===========================================================================*
27182	 *                              do_ioctl                                     *
27183	 *===========================================================================*/
27184	PUBLIC int do_ioctl()
27185	{
27186	/* Perform the ioctl(ls_fd, request, argx) system call (uses m2 fmt). */
27187	
27188	  struct filp *f;
27189	  register struct inode *rip;
27190	  dev_t dev;
27191	
27192	  if ( (f = get_filp(ls_fd)) == NIL_FILP) return(err_code);
27193	  rip = f->filp_ino;            /* get inode pointer */
27194	  if ( (rip->i_mode & I_TYPE) != I_CHAR_SPECIAL
27195	        && (rip->i_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY);
27196	  dev = (dev_t) rip->i_zone[0];
27197	  find_dev(dev);
27198	
27199	  dev_mess= m;
27200	
27201	  dev_mess.m_type  = DEV_IOCTL;
27202	  dev_mess.PROC_NR = who;
27203	  dev_mess.TTY_LINE = minor;    
27204	
27205	  /* Call the task. */
27206	  (*dmap[major].dmap_rw)(task, &dev_mess);
27207	
27208	  /* Task has completed.  See if call completed. */
27209	  if (dev_mess.REP_STATUS == SUSPEND) {
27210	        if (f->filp_flags & O_NONBLOCK) {
27211	                /* Not supposed to block. */
27212	                dev_mess.m_type = CANCEL;
27213	                dev_mess.PROC_NR = who;
27214	                dev_mess.TTY_LINE = minor;
27215	                (*dmap[major].dmap_rw)(task, &dev_mess);
27216	                if (dev_mess.REP_STATUS == EINTR) dev_mess.REP_STATUS = EAGAIN;
27217	        } else {
27218	                suspend(task);          /* User must be suspended. */
27219	        }
27220	  }
27221	  return(dev_mess.REP_STATUS);
27222	}
	
	
27225	/*===========================================================================*
27226	 *                              find_dev                                     *
27227	 *===========================================================================*/
27228	PRIVATE void find_dev(dev)
27229	dev_t dev;                      /* device */
27230	{
27231	/* Extract the major and minor device number from the parameter. */
27232	
27233	  major = (dev >> MAJOR) & BYTE;        /* major device number */
27234	  minor = (dev >> MINOR) & BYTE;        /* minor device number */
27235	  if (major >= max_major) {
27236	        major = minor = 0;              /* will fail with ENODEV */
27237	  }
27238	  task = dmap[major].dmap_task; /* which task services the device */
27239	}
	
	
27242	/*===========================================================================*
27243	 *                              call_task                                    *
27244	 *===========================================================================*/
27245	PUBLIC void call_task(task_nr, mess_ptr)
27246	int task_nr;                    /* which task to call */
27247	message *mess_ptr;              /* pointer to message for task */
27248	{
27249	/* All file system I/O ultimately comes down to I/O on major/minor device
27250	 * pairs.  These lead to calls on the following routines via the dmap table.
27251	 */
27252	
27253	  int r, proc_nr;
27254	  message local_m;
27255	
27256	  proc_nr = mess_ptr->PROC_NR;
27257	
27258	  while ((r = sendrec(task_nr, mess_ptr)) == ELOCKED) {
27259	        /* sendrec() failed to avoid deadlock. The task 'task_nr' is
27260	         * trying to send a REVIVE message for an earlier request.
27261	         * Handle it and go try again.
27262	         */
27263	        if ((r = receive(task_nr, &local_m)) != OK) break;
27264	
27265	        /* If we're trying to send a cancel message to a task which has just
27266	         * sent a completion reply, ignore the reply and abort the cancel
27267	         * request. The caller will do the revive for the process. 
27268	         */
27269	        if (mess_ptr->m_type == CANCEL && local_m.REP_PROC_NR == proc_nr)
27270	                return;
27271	
27272	        /* Otherwise it should be a REVIVE. */
27273	        if (local_m.m_type != REVIVE) {
27274	                printf(
27275	                "fs: strange device reply from %d, type = %d, proc = %d\n",
27276	                        local_m.m_source,
27277	                        local_m.m_type, local_m.REP_PROC_NR);
27278	                continue;
27279	        }
27280	
27281	        revive(local_m.REP_PROC_NR, local_m.REP_STATUS);
27282	  }
27283	
27284	  /* The message received may be a reply to this call, or a REVIVE for some
27285	   * other process.
27286	   */
27287	  for (;;) {
27288	        if (r != OK) panic("call_task: can't send/receive", NO_NUM);
27289	
27290	        /* Did the process we did the sendrec() for get a result? */
27291	        if (mess_ptr->REP_PROC_NR == proc_nr) break;
27292	
27293	        /* Otherwise it should be a REVIVE. */
27294	        if (mess_ptr->m_type != REVIVE) {
27295	                printf(
27296	                "fs: strange device reply from %d, type = %d, proc = %d\n",
27297	                        mess_ptr->m_source,
27298	                        mess_ptr->m_type, mess_ptr->REP_PROC_NR);
27299	                continue;
27300	        }
27301	        revive(mess_ptr->REP_PROC_NR, mess_ptr->REP_STATUS);
27302	
27303	        r = receive(task_nr, mess_ptr);
27304	  }
27305	}
	
	
27308	/*===========================================================================*
27309	 *                              call_ctty                                            *
27310	 *===========================================================================*/
27311	PUBLIC void call_ctty(task_nr, mess_ptr)
27312	int task_nr;                    /* not used - for compatibility with dmap_t */
27313	message *mess_ptr;              /* pointer to message for task */
27314	{
27315	/* This routine is only called for one device, namely /dev/tty.  Its job
27316	 * is to change the message to use the controlling terminal, instead of the
27317	 * major/minor pair for /dev/tty itself.
27318	 */
27319	
27320	  int major_device;
27321	 
27322	  if (fp->fp_tty == 0) {
27323	        /* No controlling tty present anymore, return an I/O error. */
27324	        mess_ptr->REP_STATUS = EIO;
27325	        return;
27326	  }
27327	  major_device = (fp->fp_tty >> MAJOR) & BYTE;
27328	  task_nr = dmap[major_device].dmap_task;       /* task for controlling tty */
27329	  mess_ptr->DEVICE = (fp->fp_tty >> MINOR) & BYTE;
27330	  call_task(task_nr, mess_ptr);
27331	}
	
	
27334	/*===========================================================================*
27335	 *                              no_dev                                       *
27336	 *===========================================================================*/
27337	PUBLIC void no_dev(task_nr, m_ptr)
27338	int task_nr;                    /* not used - for compatibility with dmap_t */
27339	message *m_ptr;                 /* message pointer */
27340	{
27341	/* No device there. */
27342	
27343	  m_ptr->REP_STATUS = ENODEV;
27344	}

⌨️ 快捷键说明

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