linux中动态加载驱动的过程是怎么样的,能给个详细的吗

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux中动态加载驱动的过程是怎么样的,能给个详细的吗相关的知识,希望对你有一定的参考价值。

参考技术A 介绍个动态加载模块的过程

在该驱动中,我们假设对键盘的获取是以0.2s为周期执行。源代码如下

static struct timer_list timer;///////我们定义的定时器,也许你会问timer_list是什么来的,其实一看名称就应该就知道了,而为什么要用到list那么多定时器呢?其实在linux中还有很多相同的定义,比如说信号,我们定义的也是信号集,你可以定义该list是一个元素的,也可以是多个的。所以对于 timer_list就可以这样描述:在未来某一个特定时刻执行某一系列特定任务的功能。下面我们还会给出内核中timer_list的具体描述,^_^ 好像我的话又说多了

static int Keypad_starttimer(void)

init_timer(&timer);//初始化定时器结构
timer.function=Keypad_timer;//超时服务程序
timer.expires=jiffies+20;//当前时刻加0.2s
add_timer(&timer);
return 0;

///超时服务程序
static void Keypad_timer(unsigned long data)

read_xy();


/////////接下来说下timer-list这个数据结构,如果你不感兴趣的话可以跳过,该结构在include\linux\timer.h中定义
struct timer_list

struct list_head entry;
unsigned long expries;
spinlock_t lock;
unsigned long magic;
void (*function)(unsigned long);
unsigner long data;
struct tvec_t_base_s *base;


七.利用等待队列实现阻塞型I\O

在用户程序执行读操作的时候有可能尚且没有数据可以读取,为此需要让read操作等待,直到有数据可以读取,这就是阻塞型i\o,阻塞型io可以通过使用进程休眠方法实现。在无数据可以读取的时候,采用等待队列让进程休眠,直到有数据到达的时候才唤醒进程完成数据的读操作。

在本驱动中的read,若循环队列缓冲区中没有数据,则进程进入休眠态,定时器函数每隔0.2s读取键值一次,将按键状态放入缓冲并且适时唤醒进程读取数据。

等待队列的使用流程如下:

1.声明一个等待队列

2.把当前进程加入到等待队列中

3.把进程的状态设置为TASK_INTERRUPTIBLE或TASK_UNINTERRUPTIBLE;

4.调用schedule,以让出cpu

5.检测所需要的资源是否可用,若是,把当前进程从等待队列中删除,否则转3循环

接下来我们在对read中有关等待队列阻塞实现做具体的解释

static ssize_t Keypad_read(struct file *filp,char *buf,ssize_t count,loff_t *l)

DECLEARE_WAITQUEUE(wait,current);//声明等待队列,将当前进程加入到等待队列中
KEY_EVENT t;
ulong out_buf[2];
if(head==tail)//当前循环队列中没有数据可以读取

if(filp->f_flags & O_NONBLOCK)//假如用户采用的是非堵塞方式读取
return _EAGAIN;
add_wait_queue(&queue,&wait);//将当前进程加入等待队列
current->state=TASK_INTERRUPTIBLE;//设置当前进程的状态
while((head==tail)&&!signal_pending(current))//假若还没有数据到循环队列并且当前进程没有受到信号(该类信号具体来说是未决的休眠)

shedule();//进程调度
current->state=TASK_INTERRUPTIBLE;

current->state=TASK_RUNNING;//该进程恢复执行
remove_wait_queue(&queue,&wait);//移出等待队列
if(head==tail)
return count;
t=get_data();//调用get_data()函数,得到缓冲区中的数据,下面将给予详细的 介绍
out_buf[0]=t.status;
out_buf[1]=t.click;
copy_to_user(buf,&out_buf,sizeof(out_buf));//将得到的键值拷贝到用户数据区
return count;

追问

呵呵,谢谢你回答了这么多,但我想知道的是如何加载到linux内核中

参考技术B 驱动的加载可以有两个不同流程。一个是driver加载后依次匹配该driver对应bus上的device,另一个是device注册后依次匹配该device对应bus上的driver。下面总结下函数调用的流程:

1)driver匹配device:

i2c_register_driver
driver_register
bus_add_driver
bus_for_each_dev:使用这个driver和bus上所有的device匹配
__driver_attach
driver_probe_device:这个函数和用来匹配driver和device,device流程也调用这个函数
i2c_device_probe
w83l604g_probe

2)device匹配driver:

i2c_new_device
device_add
bus_probe_device:device_add调用bus_probe_device检测设备
device_attach
bus_for_each_drv:device_attach通过调用bus_for_each_drv来匹配bus上的所有driver
driver_probe_device
i2c_device_probe:会通过really_probe调用bus的probe函数,从而真正的匹配driver和device
mt9v113_camera_probe:最终的driverprobe函数

以上是关于linux中动态加载驱动的过程是怎么样的,能给个详细的吗的主要内容,如果未能解决你的问题,请参考以下文章

VC中Tab控件怎么能够动态的增加标签,删除标签,就像浏览器那样的,能给个具体例子更好,谢谢了哈

Android SDK到底怎么安装啊?我双击了SDK Manager.exe,等进度条第一次加载后就一直不动了,谁能给个教程

linux如何加载驱动

嵌入式Linux驱动程序开发学习路线?

Linux驱动之内核加载模块过程分析

谁能给个简单的JAVA连接MYSQL实现增删改查的实例.谢谢了啊,我的邮箱是ah1363454335@qq.com