2009年12月24日 星期四

Linux Kernel(6)- miscdev


有時候我們需要寫一些"小的驅動程式",而早期的UNIX/Linux需要註冊major/minor number,即便可能只需要1個minor number,往往卻佔住major number底下的所有minor number,於是在Linux 2.0有了miscellaneous character drivers的誕生,misc driver使用major number 10,然後使用者如果需要這樣的"小驅動程式",便可以指明minor number即可。

使用misc device必須include <linux/miscdevice.h>,裡面包含了許多的官方的minor number,您可以挑選您適合的minor number,裡面也包含了兩個API,misc_register()/misc_deregister()。
一般您只要填好struct miscdevice的內容,再使用misc_register()進行註冊,或者使用misc_deregister()進行移除即可。
struct miscdevice  {
 int minor;
 const char *name;
 const struct file_operations *fops;
 struct list_head list;
 struct device *parent;
 struct device *this_device;
 const char *devnode;
};
 minor:就是您要註冊的minor number。
 name:device的name。
 fops:file operations。
 其他的就不用理會了。

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
MODULE_LICENSE("GPL");

#define DEV_BUFSIZE 1024

static int dev_open(struct inode*, struct file*);
static int dev_release(struct inode*, struct file*);
static ssize_t dev_read(struct file*, char __user*, size_t, loff_t*);
static ssize_t dev_write(struct file*, const char __user *, size_t, loff_t*);
static void __exit exit_modules(void);

static struct file_operations dev_fops = {
    .owner = THIS_MODULE,
    .open = dev_open,
    .release = dev_release,
    .read = dev_read,
    .write = dev_write,
};

static struct miscdevice brook_miscdev = {
    .minor      = 11,
    .name       = "brook_dev",
    .fops       = &dev_fops,
};

static int
dev_open(struct inode *inode, struct file *filp)
{
    printk("%s():\n", __FUNCTION__);
    return 0;
}

static int
dev_release(struct inode *inode, struct file *filp)
{
    printk("%s():\n", __FUNCTION__);
    return 0;
}

static ssize_t
dev_read(struct file *filp, char __user *buf, size_t count, loff_t *pos)
{
    printk("%s():\n", __FUNCTION__);
    *pos = 0;
    return 0;
}

static ssize_t
dev_write(struct file *filp, const char __user *buf,
        size_t count, loff_t *pos)
{
    printk("%s():\n", __FUNCTION__);
    return count;
}

static int __init init_modules(void)
{
    int ret;

    ret = misc_register(&brook_miscdev);
    if (ret != 0) {
        printk("cannot register miscdev on minor=11 (err=%d)\n",ret);
    }

    return 0;
}

static void __exit exit_modules(void)
{
    misc_deregister(&brook_miscdev);
}

module_init(init_modules);
module_exit(exit_modules);



2009年12月23日 星期三

vbindiff - Visual Binary Diff


VBinDiff是一套視窗化的二進位diff工具,可以將檔案內容以16和ASCII方式顯示(和早期的PCTOOL感覺很像)。


官方網站:
http://www.cjmweb.net/vbindiff/


2009年12月20日 星期日

Linux Kernel(4.2)- seq_file之single page


對於只有一頁的輸出,seq_file中的sart()/next()/stop()就顯得多餘,通常指需要一個show(),所以,seq_file也提供單頁的版本single_open(),以下範例為fs/proc/cmdline.c:
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>

static int cmdline_proc_show(struct seq_file *m, void *v)
{
 seq_printf(m, "%s\n", saved_command_line);
 return 0;
}

static int cmdline_proc_open(struct inode *inode, struct file *file)
{
 return single_open(file, cmdline_proc_show, NULL);
}

static const struct file_operations cmdline_proc_fops = {
 .open  = cmdline_proc_open,
 .read  = seq_read,
 .llseek  = seq_lseek,
 .release = single_release,
};

static int __init proc_cmdline_init(void)
{
 proc_create("cmdline", 0, NULL, &cmdline_proc_fops);
 return 0;
}
module_init(proc_cmdline_init);
和seq_file的不同在於,因為只有一頁所以不需要sart()/next()/stop(),就只剩下show(),再來就是要用single_open()取代seq_open()。而relese也是要使用single_release()取代seq_release()。


熱門文章