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()。
標籤:
Linux - kernel
2009年12月16日 星期三
Linux Kernel(5)- ioctl
(V)將介紹file operations中的ioctl。ioctl的prototype為:
int (*ioctl) (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
ioctl藉由cmd來判斷後面所接的參數為何,而早期的ioctl號碼並沒有規則,所以很容易重複,後來為了避免重複,採行編碼方式,將cmd拆成幾個部份,包含:
type:
即magic number,可以根據Document/ioctl/ioctl-number.txt挑選一個。
number:
為sequential number或者稱為ordinal number,讓user自行定義,只要自己不重複即可。
direction:
傳輸的方向,不外乎NONOE/READ/WRITE等等。
size:
即參數的size。
因為ioctl藉由cmd來判斷user想要的指令為何,以及後面所帶的參數為何,所以免不了的就會有一個switch/case來判斷,這也算是ioctl的特色吧。
怎麼定義ioctl的command以及如何解譯ioctl的command,我想直接拿ioctl.h來說明。
#define _IOC(dir,type,nr,size) \ (((dir) << _IOC_DIRSHIFT) | \ ((type) << _IOC_TYPESHIFT) | \ ((nr) << _IOC_NRSHIFT) | \ ((size) << _IOC_SIZESHIFT)) /* used to create numbers */ #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) #define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) #define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) #define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) /* used to decode ioctl numbers.. */ #define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) #define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) #define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) #define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)在定義ioctl的command時,我們會根據資料傳輸的方向使用_IO(不需要傳輸資料)/_IOR(讀取)/_IOW(寫入)/_IOWR(讀寫),type是我們挑選的magic number,nr即number,是流水號,size,就是the size of argument,下面是我們的範例brook_ioctl.h:
#ifndef IOC_BROOK_H #define IOC_BROOK_H #define BROOK_IOC_MAGIC 'k' #define BROOK_IOCSETNUM _IOW(BROOK_IOC_MAGIC, 1, int) #define BROOK_IOCGETNUM _IOR(BROOK_IOC_MAGIC, 2, int) #define BROOK_IOCXNUM _IOWR(BROOK_IOC_MAGIC, 3, int) #define BROOK_IOC_MAXNR 3 #endif這邊定義三個ioctl的command,分別為設定數值(BROOK_IOCSETNUM),取得數值(BROOK_IOCGETNUM)和交換數值(BROOK_IOCXNUM)。
以下是我的module:
#include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> // chrdev #include <linux/cdev.h> // cdev_add()/cdev_del() #include <linux/semaphore.h> // up()/down_interruptible() #include <asm/uaccess.h> // copy_*_user() #include "ioc_brook.h" MODULE_LICENSE("GPL"); #define DEV_BUFSIZE 1024 static int dev_major; static int dev_minor; struct cdev *dev_cdevp = NULL; static int dev_open(struct inode*, struct file*); static int dev_release(struct inode*, struct file*); static int dev_ioctl(struct inode*, struct file*, unsigned int, unsigned long); static void __exit exit_modules(void); struct file_operations dev_fops = { .owner = THIS_MODULE, .open = dev_open, .release = dev_release, .ioctl = dev_ioctl }; 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 int brook_num = 0; static int dev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long args) { int tmp, err = 0, ret = 0; if (_IOC_TYPE(cmd) != BROOK_IOC_MAGIC) return -ENOTTY; if (_IOC_NR(cmd) > BROOK_IOC_MAXNR) return -ENOTTY; if (_IOC_DIR(cmd) & _IOC_READ) { err = !access_ok(VERIFY_WRITE, (void __user*)args, _IOC_SIZE(cmd)); } else if (_IOC_DIR(cmd) & _IOC_WRITE) { err = !access_ok(VERIFY_READ, (void __user *)args, _IOC_SIZE(cmd)); } if (err) return -EFAULT; switch (cmd) { case BROOK_IOCSETNUM: // don't need call access_ok() again. using __get_user(). ret = __get_user(brook_num, (int __user *)args); printk("%s(): get val = %d\n", __FUNCTION__, brook_num); break; case BROOK_IOCGETNUM: ret = __put_user(brook_num, (int __user *)args); printk("%s(): set val to %d\n", __FUNCTION__, brook_num); break; case BROOK_IOCXNUM: tmp = brook_num; ret = __get_user(brook_num, (int __user *)args); if (!ret) { ret = __put_user(tmp, (int __user *)args); } printk("%s(): change val from %d to %d\n", __FUNCTION__, tmp, brook_num); break; default: /* redundant, as cmd was checked against MAXNR */ return -ENOTTY; } return 0; } static int __init init_modules(void) { dev_t dev; int ret; ret = alloc_chrdev_region(&dev, 0, 1, "brook"); if (ret < 0) { printk("can't alloc chrdev\n"); return ret; } dev_major = MAJOR(dev); dev_minor = MINOR(dev); printk("register chrdev(%d,%d)\n", dev_major, dev_minor); dev_cdevp = kmalloc(sizeof(struct cdev), GFP_KERNEL); if (dev_cdevp == NULL) { printk("kmalloc failed\n"); goto failed; } cdev_init(dev_cdevp, &dev_fops); dev_cdevp->owner = THIS_MODULE; ret = cdev_add(dev_cdevp, MKDEV(dev_major, dev_minor), 1); if (ret < 0) { printk("add chr dev failed\n"); goto failed; } return 0; failed: if (dev_cdevp) { kfree(dev_cdevp); dev_cdevp = NULL; } return 0; } static void __exit exit_modules(void) { dev_t dev; dev = MKDEV(dev_major, dev_minor); if (dev_cdevp) { cdev_del(dev_cdevp); kfree(dev_cdevp); } unregister_chrdev_region(dev, 1); printk("unregister chrdev\n"); } module_init(init_modules); module_exit(exit_modules);在dev_ioctl()先檢視command的type(magic number)和number(sequential number)是否正確,接著在根據command的read/write特性,使用access_ok()檢驗該位址是否合法,後面就是ioctl慣有的switch/case了,根據不同的case執行不同的command和解釋後面所攜帶的參數。
底下是我的application:
#include <stdio.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "ioc_brook.h" int main(int argc, char *argv[]) { int fd, ret; if (argc < 2) { printf("Usage: prog在app.c中,將開啟上面註冊的device,並且設定數值(BROOK_IOCSETNUM),讀取數值(BROOK_IOCGETNUM),和交換數值(BROOK_IOCXNUM)。\n"); return -1; } fd = open(argv[1], O_RDWR); if (fd < 0) { printf("open %s failed\n", argv[1]); return -1; } ret = 10; if (ioctl(fd, BROOK_IOCSETNUM, &ret) < 0) { printf("set num failed\n"); return -1; } if (ioctl(fd, BROOK_IOCGETNUM, &ret) < 0) { printf("get num failed\n"); return -1; } printf("get value = %d\n", ret); ret = 100; if (ioctl(fd, BROOK_IOCXNUM, &ret) < 0) { printf("exchange num failed\n"); return -1; } printf("get value = %d\n", ret); return 0; }
標籤:
Linux - kernel
訂閱:
文章 (Atom)
熱門文章
-
轉自 http://www.wretch.cc/blog/redsonoma/14021073 基本概念: 1> tty(終端設備的統稱): tty一詞源於Teletypes,或者teletypewriters,原來指的是電傳打字機,是通過串行線用打印機鍵盤通過閱...
-
Work queue提供一個interface,讓使用者輕易的建立kernel thread並且將work綁在這個kernel thread上面,如下圖[1]所示。 由於work queue是建立一個kernel thread來執行,所以是在process context...
-
(V)將介紹file operations中的ioctl。ioctl的prototype為: int (*ioctl) (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); ...
-
這兩天電腦的word忽然都不能存檔,即便是另存新檔也不行,最後都只能放棄修改檔案,即便重新安裝過或者更新成2007也都不能存檔,最後就乖乖的google一下,原來是暫存的資料夾不存在,按照以下方式就可以解決了。 資料來源: word 2003不能存檔問題 編輯機碼的(reg...
-
System Call在HW和user space提供一層抽象層,主要目的有: 為user space提供硬體抽象層。比如,讀取檔案時,不用管檔案所在的媒體類型與檔案儲存類型。 System call能確保系統的安全與穩定。避免user space的無意或惡意的破壞。 ...
-
在kernel中建立thread可以使用kthread_create(),建立一個task,然後在調用wake_up_process(task)讓task真正的運行,如果要kill一個kthread可以使用kthread_stop()。 在kernel中,將kthread_cr...
-
Linux module練習手札I紀錄如何撰寫一個簡單的module,並且編輯它,以及load和unload一個module。 write a module #include <linux/init.h> #include <linux/module.h...
-
幾乎任何使用 TCP,UDP或UNIX-domain socket的動作都可以用nc來達成,常見的功能如。 simple TCP proxies shell-script based HTTP clients and servers network daemon testi...
-
很多人心中都有過一個問題 What is the difference between Platform driver and normal device driver? ,簡單的來說Platform devices就non-discoverable,也就是device本身沒辦法...
-
組成元件 要能正確顯示資料,必須包含資料倉儲(Store),資料欄位的定義(ColumnModel)。 首先我們先定義資料欄位: var cm = new Ext.grid.ColumnModel({ {header: 'Name', dataIndex...