Linux kernel module beginning (I)

25 May 2020

Post Tags

Linux kernel Dirver

(1).Envirnoment prepare & module insert

Linux concerns kernel module version critically and it refuses to load kernel drivers that do not match. So at least the Minor version we use to do cross-compiling should match with the target platform. The download address can be find linux kernel download. Or using following command to get history version

sudo wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-x.x.xx.tar.xz

To cross-compile linux kernel, some configurations should be done first. The gui menu can be used by

make menuconfig

This simply gui can add the kernel module support for our kernel and customize the kernel. Using load from linux-x.x.xx/arch/arm/configs can some default platforms. When finish loading and modifying ‘config’ file save it to linux-x.x.xx/.config path. Later the makefile will call the configuration file when doing ‘make’.

Before using the following make command to compile the kernel, making sure the gcc-gnueabinf installed.

make ARCH=arm -j8 CROSS_COMPILE=arm-linux-gnueabihf-

A kernel zImage is generated in arch/boot, also now we can using the header file in linux-x.x.xx/include to make our kernel modules.

In our customized kernel module, ‘makefile’ will call the phony command make modules in makefile under linux-x.x.xx which help us compile and link the corresponding linux kernel library.

KERNEL_DIR=/home/$(your_linux-x.x.xx)
obj-m := helloworld.o
all:
$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean

With the command insmod, the module will be inserted into the kernel (Tips: printk function may not print in the terminal, in that case, echo 8 > /proc/sys/kernel/printk ):

ismod

(2) register the character device into kernel

A typical character device driver may include following components.

  1. initial & exit function (initial and delete driver module)
  2. register & unregister function (inside initial, exit function and used for configurating operations of drivers)
  3. file_operation structure (include basic operation accept by drives like: open,read,write and etc..)
  • A basic initial and exit function is shown below:
#define CHRDEVTEST_MAJOR 248
#define CHRDEVTEST_NAME "EmbedCharDev"

static int __init chrdevtest_init(void){
    int ret;
    ret = register_chrdev( CHRDEVTEST_MAJOR, CHRDEVTEST_NAME, &chrdevtest_fops);
    if(ret<0){
        printk("chrdevtest_init failed \n");
    }
    return 0;
} 

static void __exit chrdevtest_exit(void){

    unregister_chrdev( CHRDEVTEST_MAJOR, CHRDEVTEST_NAME);
}
  • Here, the chrdevtest_fops is a realization of file_operation structure. Inside the structure, the corresponding operations can be configured by using function pointer:
static struct file_operations chrdevtest_fops={
    .owner = THIS_MODULE,
    .open = chrdevtest_open,
    .release = chrdevtest_release,
    .read = chrdevtest_read,
    .write = chrdevtest_write,
};
  • Some simple example of operation function is shown below:
static int chrdevtest_open(struct inode *inode, struct file *filp){
    printk("chrdevtest_open \n");
    return 0;
}

static int chrdevtest_release(struct inode *inode, struct file *filp){
    printk("chrdevtest_release \n");
    return 0;
}

static ssize_t chrdevtest_read(struct file *filp, char __user * buf, size_t count, loff_t *ppos)
{
    printk("chrdevtest_read \n");
    return 0;
 }

static ssize_t chrdevtest_write(struct file *filp, const char __user * buf, size_t count, loff_t *ppos)
{
    printk("chrdevtest_write \n");
    return 0;
 }

After inserting kernel module, the kernel module name and it major id can be seen under /proc/devices.
cat /proc/devices

<p>Figure. Major deive ID </p>

Using mknod /dev/<name> c major_id minor_id to creat a device, the deivce will be show at /dev
mknod /dev/chrdev1 c 248 0

Or using device_create automatically creat a device inside dirver. ` device = device_create(class, NULL, devid, NULL, DEV_NAME); `


Post Tags

Linux kernel Dirver