这个事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);
}