现在的位置: 首页 > 综合 > 正文

阻塞式IO(就是多个打开当前的open不返回,直到别人用完close了)

2013年08月03日 ⁄ 综合 ⁄ 共 3051字 ⁄ 字号 评论关闭

这个事LKMG中的例子:

 

 #include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
#include <linux/proc_fs.h> /* Necessary because we use proc fs */
#include <linux/sched.h> /* For putting processes to sleep and
       waking them up */
#include <asm/uaccess.h> /* for get_user and put_user */

#define MESSAGE_LENGTH 80
static char Message[MESSAGE_LENGTH];

static struct proc_dir_entry *Our_Proc_File;
#define PROC_ENTRY_FILENAME "sleep"

static ssize_t module_output(struct file *file, /* see include/linux/fs.h   */
        char *buf, /* The buffer to put data to
        (in the user segment)    */
        size_t len, /* The length of the buffer */
        loff_t * offset)
{
 static int finished = 0;
 int i;
 char message[MESSAGE_LENGTH + 30];

 if (finished) {
  finished = 0;
  return 0;
 }

 
 sprintf(message, "Last input:%s/n", Message);
 for (i = 0; i < len && message[i]; i++)
  put_user(message[i], buf + i);

 finished = 1;
 return i;  /* Return the number of bytes "read" */
}

static ssize_t module_input(struct file *file, /* The file itself */
       const char *buf, /* The buffer with input */
       size_t length, /* The buffer's length */
       loff_t * offset)
{    /* offset to file - ignore */
 int i;

 
 for (i = 0; i < MESSAGE_LENGTH - 1 && i < length; i++)
  get_user(Message[i], buf + i);
 
 Message[i] = '/0';

 
 return i;
}

int Already_Open = 0;

DECLARE_WAIT_QUEUE_HEAD(WaitQ);

static int module_open(struct inode *inode, struct file *file)
{
 
 if ((file->f_flags & O_NONBLOCK) && Already_Open) ----以非阻塞打开,立即返回
  return -EAGAIN;

 try_module_get(THIS_MODULE);

 while (Already_Open) {
  int i, is_sig = 0;

 
  wait_event_interruptible(WaitQ, !Already_Open);-----------已经打开,就在这等,直到别人调用了close或者接收到ctrl+c信号

  for (i = 0; i < _NSIG_WORDS && !is_sig; i++)
   is_sig =
       current->pending.signal.sig[i] & ~current->   ---------------对抢占的处理,如果被抢占就手动减少模块计数。
       blocked.sig[i];

  if (is_sig) {
   
   module_put(THIS_MODULE);
   return -EINTR;
  }
 }

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

int module_close(struct inode *inode, struct file *file)
{
 
 Already_Open = 0;

 
 wake_up(&WaitQ);          --------------------唤醒等待队列,让它去查Already_Open这个标志。

 module_put(THIS_MODULE);

 return 0;  /* success */
}

static int module_permission(struct inode *inode, int op, struct nameidata *nd)
{
 
 if (op == 4 || (op == 2 && current->euid == 0))
  return 0;

 return -EACCES;
}

static struct file_operations File_Ops_4_Our_Proc_File = {
 .read = module_output, /* "read" from the file */
 .write = module_input, /* "write" to the file */
 .open = module_open, /* called when the /proc file is opened */
 .release = module_close, /* called when it's closed */
};

 

static struct inode_operations Inode_Ops_4_Our_Proc_File = {
 .permission = module_permission, /* check for permissions */
};

int init_module()
{
 int rv = 0;
 Our_Proc_File = create_proc_entry(PROC_ENTRY_FILENAME, 0644, NULL);
 Our_Proc_File->owner = THIS_MODULE;
 Our_Proc_File->proc_iops = &Inode_Ops_4_Our_Proc_File;
 Our_Proc_File->proc_fops = &File_Ops_4_Our_Proc_File;
 Our_Proc_File->mode = S_IFREG | S_IRUGO | S_IWUSR;
 Our_Proc_File->uid = 0;
 Our_Proc_File->gid = 0;
 Our_Proc_File->size = 80;

 if (Our_Proc_File == NULL) {
  rv = -ENOMEM;
  remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
  printk(KERN_INFO "Error: Could not initialize /proc/test/n");
 }

 return rv;
}

void cleanup_module()
{
 remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
}

抱歉!评论已关闭.