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

📄 9.html

📁 linux操作系统内核编程-----LINUX系统开发非常好的资料
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<html><head><title>黄金书屋</title><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><link rel="stylesheet" href="/goldnets.css"></head><body bgcolor="#E4EBF1"><center><a href="http://ad.myrice.com/RealMedia/ads/click_nx.ads/goldnets.myrice.com/banner1@Top" target=_blanck ><script language=JavaScript><!---todayd = new Date();var seconds = todayd.getTime();document.write("<img src=\"http://ad.myrice.com/RealMedia/ads/adstream_nx.ads/goldnets.myrice.com/banner1@Top?dd=seconds\" border=0 width=468 height=60>");//--></script></a></center><br><table width="756" border="0" cellspacing="0" cellpadding="0" align="center" bgcolor="#E4EBF1">  <tr>    <td colspan="2" valign="top" align="center">      <div align="center">        <table width="100%" border="0" cellspacing="0" cellpadding="0" height="52">          <tr>            <td valign="top"><br>              <div align="center">                <table width="100%" border="0" cellspacing="0" cellpadding="0">                  <tr>                    <td valign="bottom">                      <table width="100%" border="0" cellspacing="0" cellpadding="0">                        <tr>                          <td><a href="/index.html">首页</a>&gt;&gt; <font color="#CC0000"><a href="/book/152/1015178.html">Linux内核编程</a></font></td>                          <td width="22%"> <a href="/index.html">[ 点此回首页 ]</a></td>                        </tr>                        <tr>                          <td colspan="2"><img src="/image/1x1.gif" width="1" height="2"></td>                        </tr>                        <tr bgcolor="#FFCC00">                          <td colspan="2"><img src="/image/1x1.gif" width="1" height="1"></td>                        </tr>                        <tr>                          <td colspan="2"><img src="/image/1x1.gif" width="1" height="6"></td>                        </tr>                      </table>                    </td>                  </tr>                </table>                <br>                <table width="590" border="0" cellspacing="0" cellpadding="0">                  <tr>                    <td><center><a href='8.html'>上一页 </a>||<a href='10.html'>下一页</a></center><br><hr><div style=font-size:12pt><pre>                       5.和设备文件对话(写和IOCTLS)
设备文件是用来代表物理设备的。多数物理设备是用来进行输出或输入的,所以必须
由某种机制使得内核中的设备驱动从进程中得到输出送给设备。这可以通过打开输出设备文
件并且写入做到,就想写入一个普通文件。在下面的例子里,这由device_write实现。
这不是总能奏效的。设想你与一个连向modem的串口(技是你有一个内猫,从CPU看
来它也是作为一个串口实现,所以你不需要认为这个设想太困难)。最自然要做的事情就是
使用设备文件把内容写到modem上(无论用modem命令还是电话线)或者从modem读信
息(同样可以从modem命令回答或者通过电话线)。但是这留下的问题是当你需要和串口本
身对话的时候需要怎样做?比如发送数据发送和接收的速率。
回答是Unix使用一个叫做ioctl(input output control的简写)的特殊函数。每个设备都有
自己的ioctl命令,这个命令可以是ioctl读的,也可以是写的,也可以是两者都是或都不是。
Ioctl函数由三个参数调用:适当设备的描述子,ioctl数,和一个长整型参数,可以赋予一
个角色用来传递任何东西。
Ioctl数对设备主码、ioctl类型、编码、和参数的类型进行编码。Ioctl数通常在头文件
由一个宏调用(_IO,_IOR,_IOW或_IOWR——决定于类型)。这个头文件必须包含在使
用ioctl(所以它们可以产生正确的ioctl\'s)程序和内核模块(所以它可以理解)中。在下面
的例子里,这个头文件是chardev.h,使用它的程序是ioctl.c。
如果你希望在你自己的内核模块中使用ioctl\'s,最好去接受一分正式的ioctl职位,这样
你就可以得到别人的ioctl\'s,或者他们得到你,你就可以知道哪里出了错误。如果想得到更
多的信息,到\'documentation/ioctl-number.txt\'中查看内核源文件树。
ex chardev.c    
 
/* chardev.c 
 * 
 * Create an input/output character device
 */


/* Copyright (C) 1998-99 by Ori Pomerantz */



/* The necessary header files */

/* Standard in kernel modules */
#include <linux/kernel.h>   /* We\'re doing kernel work */
#include <linux/module.h>   /* Specifically, a module */

/* Deal with CONFIG_MODVERSIONS */
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif        

/* For character devices */

/* The character device definitions are here */
#include <linux/fs.h>       

/* A wrapper which does next to nothing at
 * at present, but may help for compatibility
 * with future versions of Linux */
#include <linux/wrapper.h>  

			     
/* Our own ioctl numbers */
#include \"chardev.h\"


/* In 2.2.3 /usr/include/linux/version.h includes a 
 * macro for this, but 2.0.35 doesn\'t - so I add it 
 * here if necessary. */
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))
#endif



#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
#include <asm/uaccess.h>  /* for get_user and put_user */
#endif



#define SUCCESS 0


/* Device Declarations ******************************** */


/* The name for our device, as it will appear in 
 * /proc/devices */
#define DEVICE_NAME \"char_dev\"


/* The maximum length of the message for the device */
#define BUF_LEN 80

/* Is the device open right now? Used to prevent 
 * concurent access into the same device */
static int Device_Open = 0;

/* The message the device will give when asked */
static char Message[BUF_LEN];

/* How far did the process reading the message get? 
 * Useful if the message is larger than the size of the 
 * buffer we get to fill in device_read. */
static char *Message_Ptr;


/* This function is called whenever a process attempts 
 * to open the device file */
static int device_open(struct inode *inode, 
                       struct file *file)
{
#ifdef DEBUG
  printk (\"device_open(%p)\\n\", file);
#endif

  /* We don\'t want to talk to two processes at the 
   * same time */
  if (Device_Open)
    return -EBUSY;

  /* If this was a process, we would have had to be 
   * more careful here, because one process might have 
   * checked Device_Open right before the other one 
   * tried to increment it. However, we\'re in the 
   * kernel, so we\'re protected against context switches.
   *
   * This is NOT the right attitude to take, because we
   * might be running on an SMP box, but we\'ll deal with
   * SMP in a later chapter.
   */ 

  Device_Open++;

  /* Initialize the message */
  Message_Ptr = Message;

  MOD_INC_USE_COUNT;

  return SUCCESS;
}


/* This function is called when a process closes the 
 * device file. It doesn\'t have a return value because 
 * it cannot fail. Regardless of what else happens, you 
 * should always be able to close a device (in 2.0, a 2.2
 * device file could be impossible to close). */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static int device_release(struct inode *inode, 
                          struct file *file)
#else
static void device_release(struct inode *inode, 
                           struct file *file)
#endif
{
#ifdef DEBUG
  printk (\"device_release(%p,%p)\\n\", inode, file);
#endif
 
  /* We\'re now ready for our next caller */
  Device_Open --;

  MOD_DEC_USE_COUNT;

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



/* This function is called whenever a process which 
 * has already opened the device file attempts to 
 * read from it. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static ssize_t device_read(
    struct file *file,
    char *buffer, /* The buffer to fill with the data */   
    size_t length,     /* The length of the buffer */
    loff_t *offset) /* offset to the file */
#else
static int device_read(
    struct inode *inode,
    struct file *file,
    char *buffer,   /* The buffer to fill with the data */ 
    int length)     /* The length of the buffer 
                     * (mustn\'t write beyond that!) */
#endif
{
  /* Number of bytes actually written to the buffer */
  int bytes_read = 0;

#ifdef DEBUG
  printk(\"device_read(%p,%p,%d)\\n\",
    file, buffer, length);
#endif

  /* If we\'re at the end of the message, return 0 
   * (which signifies end of file) */
  if (*Message_Ptr == 0)
    return 0;

  /* Actually put the data into the buffer */
  while (length && *Message_Ptr)  {

    /* Because the buffer is in the user data segment, 
     * not the kernel data segment, assignment wouldn\'t 
     * work. Instead, we have to use put_user which 
     * copies data from the kernel data segment to the 
     * user data segment. */
    put_user(*(Message_Ptr++), buffer++);
    length --;
    bytes_read ++;
  }

#ifdef DEBUG
   printk (\"Read %d bytes, %d left\\n\",
     bytes_read, length);
#endif

   /* Read functions are supposed to return the number 
    * of bytes actually inserted into the buffer */
  return bytes_read;
}


/* This function is called when somebody tries to 
 * write into our device file. */ 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static ssize_t device_write(struct file *file,
                            const char *buffer,
                            size_t length,
                            loff_t *offset)
#else
static int device_write(struct inode *inode,
                        struct file *file,
                        const char *buffer,
                        int length)
#endif
{
  int i;

#ifdef DEBUG
  printk (\"device_write(%p,%s,%d)\",
    file, buffer, length);
#endif

  for(i=0; i<length && i<BUF_LEN; i++)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
    get_user(Message[i], buffer+i);
#else
    Message[i] = get_user(buffer+i);
#endif  

  Message_Ptr = Message;

  /* Again, return the number of input characters used */
  return i;
}


/* This function is called whenever a process tries to 
 * do an ioctl on our device file. We get two extra 
 * parameters (additional to the inode and file 
 * structures, which all device functions get): the number
 * of the ioctl called and the parameter given to the 
 * ioctl function.
 *
 * If the ioctl is write or read/write (meaning output 
 * is returned to the calling process), the ioctl call 
 * returns the output of this function.
 */
int device_ioctl(
    struct inode *inode,
    struct file *file,
    unsigned int ioctl_num,/* The number of the ioctl */
    unsigned long ioctl_param) /* The parameter to it */
{
  int i;
  char *temp;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
  char ch;
#endif

  /* Switch according to the ioctl called */
  switch (ioctl_num) {

⌨️ 快捷键说明

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