The process of calling the driver in c language and the application program accessing the character device driver

1. Install the character device driver

1.0

Allocate an underlying driver set of operations

struct file_operations led_fops = {

.open =  led_open,

.read = led_read

}

1.1 Allocating struct cdev

1.2 Call cdev_init to initialize cdev

cdev->ops =

&led_fops

1.3 Call cdev_add to register the allocated cdev in a cdev array in the kernel, and place the device number as an index.

2. When the application calls open

2.1 The application calls open

2.2 Save the system call number corresponding to open to the register

2.3 Call swi to trigger a soft interrupt exception

2.4 The CPU will transfer to the entry address vector_swi of an exception vector table defined by the kernel implementation

2.5 Find the corresponding system call function sys_open in a system call table prepared by the kernel implementation according to the system call number

2.6 First obtain the device number information through inode->i_rdev in sys_open

2.7 Find the corresponding driver cdev in the kernel's cdev array according to the device number

2.8 After finding cdev, assign this cdev to inode->icdev for caching

2.9 Create struct

file object, take out the operation set ops of the underlying driver from the cdev remembered in step 2.7, and assign this ops to file-f_os

2.10 If there is an open function in ops in the underlying driver,

Then the underlying driver's open will eventually be called

file->f_op->open

2.11 After executing the open of the underlying driver, return to the open of the application in the same way

The application wants to read the device information

1. The premise is that the driver is installed

2. The premise is that the device is open successfully, indicating inode, file, cdev,

The four structures of file_operations have established a good relationship

3. The application calls read->sys_read;

3.1 Get file

3.2 Direct file->f_op->read();

Summarize:

For implementing a driver, just wrap around the struct

cdev和 struct file_operations 结构体即可.

案例:应用程序调用open时打开所有的灯

应用程序调用close时,关闭所有的灯

1.申请设备号

2.分配cdev

3.初始化cdev

指定驱动操作集合struct

file_operations(首先分配驱动程序的集合)

3.注册cdev

vi led_drv.c

#include

#include < linux/module.h >

#include < linux/module.h

>

#include < linux/device.h >

#inlcude < linux/cdev.h >

#include< asm/gpio.h >

#include< plat/gpio-cfg.h >

staitc int major;

staitc int led_open(struct inode* inode, struct file

*file)

{

printk("%s\n",  __func__);

gpio_set_value(S5PV210_GPC1(3), 1);

return

0;

}

staitc int led_close(struct inode* inode, struct file

*file)

{

printk("%s\n", __func__);

gpio_set_value(S5PV210_GPC1(3), 0);

return

0;

}

//分配初始化驱动操作集合

static struct file_operations led_fops =

{

.owner =  THIS_MODULE,

.open =  led_open,

.release = led_close

};

//分配一个struct cdev

static struct cdev led_cdev;

static int led_init(void)

{

//1.申请设备号

dev_t dev;

alloc_chrdev_region(&dev, 0, 1, "leds");

major = MAJOR(dev);

//2.初始化cdev

cdev_init(&led_cdev,

&led_fops);

//3.注册cdev

cdev_add(&led_cdev, dev, 1);

//4.申请GPIO资源

gpio_request(S5PV210_GPC1(3), "LED1");

//5.配置GPIO为输出口, 输出0

gpio_direction_output(S5PV210_GPC1(3), 0);

return 0;

}

static void led_exit(void)

{

//1.配置GPIO为输出口, 输出0

gpio_direction_output(S5PV210_GPC1(3), 0);

//2.释放GPIO资源

gpio_free(S5PV210_GPC1(3));

//3.卸载cdev

cdev_del(&led_cdev);

//4.释放设备号

unregister_chrdev_region(MKDEV(major, 0), 1);

}

module_init(led_init);

module_exit(led_exit);

MODULE_LICENSE("GPL");

vi led_test.c

#include< stdio.h >

#include< sys/stat.h >

#include< syst/types.h >

#include< fcntl.h >

int main(void)

{

int fd;

fd = open("dev/myled",

O_RDWR);

if(fd <

0)

{

printf("open led device failed. \n");

return -1;

}

sleep (3);

fclose(fd);

}

insmod led_drv.ko

cat /proc/devices

rm /dev/mytest -fr

mknod /dev/myled c 249  0

./led_test

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324326324&siteId=291194637