1.
引用標頭檔 linux/ioctl.h
#include <linux/ioctl.h>
若 kernel 內有定義 CONFIG_COMPAT 這 defined constant
表示 ioctl 在 相容模式 (compatibility mode)
要多引用 linux/compat.h
#include <linux/compat.h>

 

2.
建立 defined constants

2.1.
建立等會建立 ioctl command 要用的 type,類似 prefix
#define TYPE 's'

#define TYPE '<char>'
<char>: 任何字元用以當 command 的 type

2.2.
建立 ioctl command
例:
#define SM_GET     _IOR(TYPE, 1, int)
#define SM_SET     _IOW(TYPE, 2, int)

定義 command 可用的 macro
_IO(<cmd type>, <number>);
_IOR(<cmd type>, <number>, <arg type>);
_IOW(<cmd type>, <number>, <arg type>);
_IOWR(<cmd type>, <number>, <arg type>);

_IO         讀寫:寫到 proc 用 arg,回傳值是要讀取的資料
_IOR      讀:把 arg 當指標從 kernel 取得資料,配合 copy_to_user() 和 put_user()
_IOW     寫:把 arg 當指標傳資料至 kernel,配合 copy_from_user() 和 get_user()
_IOWR  讀寫:把arg 當指標進行讀取與寫入,copy_from_user() 和 get_user()
                           copy_to_user() 和 put_user()

<cmd type>: 被 shift 至 <number> 前端,類似 prefix
<number>: 第幾個 command
<arg type>: 參數的型態,像是 int, long,...

2.3.
撰寫 ioctl
例:
int smalldd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
    int ret = 0;
    int value = 1;
    struct data data;

    switch(cmd)
    {
        case SM_GET:
            put_user(value, arg);

            OR
            copy_to_user((void *)arg, &data, sizeof(struct data));
            break;
        case SM_SET:
            get_user(value, arg);

            OR
            copy_from_user((void *)arg, &data, sizeof(struct data));
            break;
        default:
            break;
    }

    return ret;
}

若有定義 CONFIG_COMPAT 這 defined constant
要多撰寫相容模式的 compat_ioctl
例:
#ifdef CONFIG_COMPAT
long smalldd_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    return smalldd_ioctl(NULL, file, cmd, arg);
}
#endif

2.4.
建立 file_operations
順道加入 compat_ioctl
例:
struct file_operations smalldd_fops
{
    .owner = THIS_MODULE,
    .ioctl = smalldd_ioctl,
#ifdef CONFIT_COMPAT
    .compat_ioctl = smalldd_compat_ioctl,
#endif
}

 

3.
user space 的程式透過 ioctl 與 kernel space 交換資料
例:
int fd = 0;
int ret = 0;
int data = 0;  // 參數

fd = open(<file>, O_RDWR);
if(fd >= 0)
{
    ret = ioctl(fd, SM_SET, &data);  // 傳資料到 kernel space
    ret = ioctl(fd, SM_GET, &data);  //
從 kernel 取得資料
 
}

創作者介紹

小弟弟

smalldd 發表在 痞客邦 留言(0) 人氣()