iT邦幫忙

DAY 23
0

Linux kernel模組的開發系列 第 23

IOCTL 範例

因為之前介紹的網站 (http://www.tldp.org/LDP/lkmpg/2.6/html/x892.html) 上所提供的例子有錯,所以在這邊舉另一個例子。IOCTL 的範例包含 3 部分:kernel module、header file、ioctl user mode 程式。Kernel moduel 的部分是要需要建立一個 character device,以印出 "Hello ioctl world”,header file 是定義 _IO 巨集的地方,_IO macro 是要用來建裡 ioctl number 的,而 user mode 的程式是呼叫 ioctl 了範例,另外你還需要一個 Makefile 去 build 這的 module。

Compile 完之後,載入 kernel module ( insmod ioctl_basic.ko) 並從 dmesg 中去檢查 kernel moduel 的 major number,然後利用 mknod 命令去建立一個 character device file,例如,major number 是 247 的話:

mknod /dev/temp c 247 0

接著執行 user mode 程式令 kernel module 輸出訊息,接著就能在 dmesg 的輸出中看到 "Hello ioctl world”。

Makefile:

obj-m += ioctl_basic.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Kernel moduel: ioctl_basic.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h> // required for various structures related to files liked fops.
#include <linux/semaphore.h>
#include <linux/cdev.h>
#include "ioctl_basic.h"    //ioctl header file
#include <linux/version.h>
static int Major;


int open(struct inode *inode, struct file *filp)
{
 
 printk(KERN_INFO "Inside open \n");
 return 0;
}

int release(struct inode *inode, struct file *filp) {
 printk (KERN_INFO "Inside close \n");
 return 0;
}

int ioctl_funcs(struct inode *inode, struct file *filp,
                 unsigned int cmd, unsigned long arg)
{

int data=10,ret;

switch(cmd) {

case IOCTL_HELLO:
 printk(KERN_INFO "Hello ioctl world");
 break;
 }
 
return ret;
 
}

struct file_operations fops = {
 open:   open,
 ioctl:  ioctl_funcs,
 release: release
};


struct cdev *kernel_cdev;


int char_arr_init (void) {
 int ret;
 dev_t dev_no,dev;

 kernel_cdev = cdev_alloc();
  kernel_cdev->ops = &fops;
 kernel_cdev->owner = THIS_MODULE;
 printk (" Inside init module\n");
  ret = alloc_chrdev_region( &dev_no , 0, 1,"char_arr_dev");
    if (ret < 0) {
  printk("Major number allocation is failed\n");
  return ret;
 }
 
    Major = MAJOR(dev_no);
    dev = MKDEV(Major,0);
 printk (" The major number for your device is %d\n", Major);
 ret = cdev_add( kernel_cdev,dev,1);
 if(ret < 0 )
 {
 printk(KERN_INFO "Unable to allocate cdev");
 return ret;
 }

 return 0;
}

void char_arr_cleanup(void) {
 printk(KERN_INFO " Inside cleanup_module\n");
 cdev_del(kernel_cdev);
 unregister_chrdev_region(Major, 1);
}
MODULE_LICENSE("GPL");
module_init(char_arr_init);
module_exit(char_arr_cleanup);

Header file: ioctl_basic.h

#include <linux/ioctl.h>
#define IOC_MAGIC 'k'
#define IOCTL_HELLO _IO(IOC_MAGIC,0)

User mode 程式: user_basic_ioctl.c

#include <stdio.h>
#include <fcntl.h>
#include "ioctl_basic.h"  //ioctl header file

main ( ) {
 int fd;
        fd = open("/dev/temp", O_RDWR);

        if (fd == -1)
        {
                printf("Error in opening file \n");
                exit(-1);
        }
       
 ioctl(fd,IOCTL_HELLO);  //ioctl call

         close(fd);
}

上一篇
系統呼叫的範例
下一篇
Process sleep 的注意事項
系列文
Linux kernel模組的開發30

尚未有邦友留言

立即登入留言