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

📄 x1008.html

📁 linux驱动开发
💻 HTML
📖 第 1 页 / 共 2 页
字号:
      /* If we woke up because we got a signal we're not blocking, return
       * -EINTR (fail the system call).  This allows processes to be killed or
       * stopped.
       */

/*
 * Emmanuel Papirakis:
 *
 * This is a little update to work with 2.2.*.  Signals now are contained in
 * two words (64 bits) and are stored in a structure that contains an array of
 * two unsigned longs.  We now have to make 2 checks in our if.
 *
 * Ori Pomerantz:
 *
 * Nobody promised me they'll never use more than 64 bits, or that this book
 * won't be used for a version of Linux with a word size of 16 bits.  This code
 * would work in any case.
 */	  
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
      for (i = 0; i < _NSIG_WORDS && !is_sig; i++)
         is_sig = current->signal.sig[i] & ~current->blocked.sig[i];

      if (is_sig) {
#else
      if (current->signal & ~current->blocked) {
#endif
         /* It's important to put MOD_DEC_USE_COUNT here, because for processes
          * where the open is interrupted there will never be a corresponding
          * close. If we don't decrement the usage count here, we will be left
          * with a positive usage count which we'll have no way to bring down
          * to zero, giving us an immortal module, which can only be killed by
          * rebooting the machine.
          */
         MOD_DEC_USE_COUNT;
         return -EINTR;
      }
   }

   /* If we got here, Already_Open must be zero */

   /* Open the file */
   Already_Open = 1;
   return 0;                                 /* Allow the access */
}

/* Called when the /proc file is closed */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
int module_close(struct inode *inode, struct file *file)
#else
void module_close(struct inode *inode, struct file *file)
#endif
{
   /* Set Already_Open to zero, so one of the processes in the WaitQ will be
    * able to set Already_Open back to one and to open the file.  All the other
    * processes will be called when Already_Open is back to one, so they'll go
    * back to sleep.
    */
   Already_Open = 0;

   /* Wake up all the processes in WaitQ, so if anybody is waiting for the
    * file, they can have it.
    */
   module_wake_up(&WaitQ);

   MOD_DEC_USE_COUNT;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
   return 0;                                 /* success */
#endif
}

/* This function decides whether to allow an operation (return zero) or not
 * allow it (return a non-zero which indicates why it is not allowed).
 *
 * The operation can be one of the following values:
 * 0 - Execute (run the "file" - meaningless in our case)
 * 2 - Write (input to the kernel module)
 * 4 - Read (output from the kernel module)
 *
 * This is the real function that checks file permissions. The permissions
 * returned by ls -l are for referece only, and can be overridden here. 
 */
static int module_permission(struct inode *inode, int op)
{
   /* We allow everybody to read from our module, but only root (uid 0) may
    * write to it
    */ 
   if (op == 4 || (op == 2 && current->euid == 0))
      return 0; 

   /* If it's anything else, access is denied */
   return -EACCES;
}

/* Structures to register as the /proc file, with pointers to all the relevant
 * functions. 
 */

/* File operations for our proc file. This is where we place pointers to all
 * the functions called when somebody tries to do something to our file. NULL
 * means we don't want to deal with something.
 */
static struct file_operations File_Ops_4_Our_Proc_File = {
   NULL,                                   /* lseek */
   module_output,                          /* "read" from the file */
   module_input,                           /* "write" to the file */
   NULL,                                   /* readdir */
   NULL,                                   /* select */
   NULL,                                   /* ioctl */
   NULL,                                   /* mmap */
   module_open,                    /* called when the /proc file is opened */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
   NULL,                                   /* flush */
#endif
   module_close};                          /* called when it's classed */

/* Inode operations for our proc file.  We need it so we'll have somewhere to
 * specify the file operations structure we want to use, and the function we
 * use for permissions. It's also possible to specify functions to be called
 * for anything else which could be done to an inode (although we don't bother,
 * we just put NULL).
 */
static struct inode_operations Inode_Ops_4_Our_Proc_File = {
   &File_Ops_4_Our_Proc_File,
   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 */
   module_permission};                     /* check for permissions */

/* Directory entry */
static struct proc_dir_entry Our_Proc_File = {
	 0,                 /* Inode number - ignore, it will be filled by 
                       * proc_register[_dynamic]
                       */
   5,                                      /* Length of the file name */
   "sleep",                                /* The file name */

   /* File mode - this is a regular file which can be read by its owner, its
    * group, and everybody else. Also, its owner can write to it.
    *
    * Actually, this field is just for reference, it's module_permission that
    * does the actual check. It could use this field, but in our
    * implementation it doesn't, for simplicity.
    */
   S_IFREG | S_IRUGO | S_IWUSR, 
   1,        /* Number of links (directories where the file is referenced) */
   0, 0,     /* The uid and gid for the file - we give it to root */
   80,       /* The size of the file reported by ls. */

   /* A pointer to the inode structure for the file, if we need it. In our
    * case we do, because we need a write function.
    */
   &Inode_Ops_4_Our_Proc_File, 

   /* The read function for the file.  Irrelevant, because we put it in the
    * inode structure above
    */
   NULL}; 

/* Module initialization and cleanup */

/* Initialize the module - register the proc file */
int init_module()
{
   /* Success if proc_register_dynamic is a success, failure otherwise */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
   return proc_register(&proc_root, &Our_Proc_File);
#else
   return proc_register_dynamic(&proc_root, &Our_Proc_File);
#endif 

   /* proc_root is the root directory for the proc fs (/proc).  This is where
    * we want our file to be located. 
    */
}

/* Cleanup - unregister our file from /proc.  This could get dangerous if
 * there are still processes waiting in WaitQ, because they are inside our
 * open function, which will get unloaded. I'll explain how to avoid removal
 * of a kernel module in such a case in chapter 10.
 */
void cleanup_module()
{
   proc_unregister(&proc_root, Our_Proc_File.low_ino);
}  </PRE
></FONT
></TD
></TR
></TABLE
></DIV
></DIV
></DIV
><H3
CLASS="FOOTNOTES"
>Notes</H3
><TABLE
BORDER="0"
CLASS="FOOTNOTES"
WIDTH="100%"
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1048"
HREF="x1008.html#AEN1048"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>最方便的保持某个文件被打开的方法是使用命令 
			<B 
CLASS="COMMAND" 
>tail -f</B 
> 打开该文件。</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1056"
HREF="x1008.html#AEN1056"
><SPAN
CLASS="footnote"
>[2]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>这就意味着该进程仍然在内核态中——该进程已经调用了 <TT 
CLASS="FUNCTION" 
>open</TT 
>  
      的系统调用,但系统调用却没有返回。在这段时间内该进程将不会得知别人正在使用CPU。</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1077"
HREF="x1008.html#AEN1077"
><SPAN
CLASS="footnote"
>[3]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>这是因为我们使用的是 <TT 
CLASS="FUNCTION" 
>module_interruptible_sleep_on</TT 
>. 我们也可以使用 <TT 
CLASS="FUNCTION" 
>module_sleep_on</TT 
>  ,但这样会导致一些十分愤怒的用户,因为他们的 <B
CLASS="KEYCAP"
>Ctrl</B
>+<B
CLASS="KEYCAP"
>c</B
> 将不起任何作用。  </P
></TD
></TR
></TABLE
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="c1006.html"
ACCESSKEY="P"
>返回</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>返回首页</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="c1109.html"
ACCESSKEY="N"
>继续</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>阻塞进程</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="c1006.html"
ACCESSKEY="U"
>返回本章开始</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>替换 Printk</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>

⌨️ 快捷键说明

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