Linux字符设备驱动

本文围绕Linux内核展开,介绍了并发与竞态处理技术,如信号量和自旋锁机制;阐述了字符设备和块设备的访问特点;说明了主设备号和次设备号的作用;讲解了内核等待队列的定义、初始化及相关操作;还介绍了select与poll的功能、使用方法及文件描述符操作集。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、并发与竞态

1)并发

处理并发的常用技术是加锁或互斥。在Linux内核中,主要通过semaphonre机制和spin_lock机制实现

1.1)内核的信号量:是一种睡眠锁

//定义信号量

struct semaphore sem;

//初始化信号量

void sema_init(struct semaphore *sem.int val);//用于初始化设置信号量的初值

//初始化互斥锁

void init_MUTEX(struct semaphore *sem); //把信号量sem的值设置为1

void init_MUTEX)LOCKED() // 设置为0

//获取信号量,获取失败后,进程状态不一样

void down()

int down_interruptible() //进入睡眠后,可以被进程或者中断唤醒

down_killable()

2、字符设备和块设备

1)字符设备通过字节访问,块设备通过块(512,1024,4096,也可以字符)访问

2)字符设备顺序访问,块设备随机访问

 

3、主设备号和次设备号

1)主设备号:标识与设备关联的设备驱动,标识一个特定的驱动程序

2)次设备号:确定当前所指向的是哪个设备

 

4、内核等待队列

在Linux驱动程序设计中,可以使用等待队列来实现进程的阻塞,等待队列可以看作保存进程的容器,在阻塞进程时,将进程放入等待队列,当唤醒进程时,从等待队列中取出队列

//定义等待队列

wait_queue_head_t my_queue;

//初始化等待队列

init_waitqueue_head(&my_queue);

//定义并初始化等待对垒

DECLARE_WAIT_QUEUE_HEAD(my_queue);

//有条件睡眠

wait_event(queue,condition); //当condition为真时,立即但会,否则让进程进入TASK_UNINTERRUPTIBLE模式的睡眠,并挂在queue参数所指定的等待队列上

wait_event_interruptible(queue.condition); //当condition为真时,立即但会,否则让进程进入TASK_INTERRUPTIBLE模式的睡眠,并挂在queue参数所指定的等待队列上

wait_event_killable(wait_queue_t queue,condition);// 当condition为真时,立即但会,否则让进程进入TASK__KILLABLE模式的睡眠,并挂在queue参数所指定的等待队列上

//无条件睡眠

interruptible_sleep_on()

//从等待队列中唤醒进程

wake_up(wair_queue_t *q);//从等待队列q中唤醒所有进程

wake_up_interruptible(wair_queue_t *q);//唤醒状态为TASK_INTERRUPTIBLE的进程

5、select 与poll

1)poll负责完成

使用poll_wait将等待队列添加到poll_table中

返回描述设备是否可读或可写的掩码

POLLIN:设备可读

POLLRDNORM:数据可读

POLLOUT:设备可写

POLLWRNORM:数据可写

设备可读通常返回(POLLIN|POLLRDNORM)

设备可写通常返回(POLLOUT|POLLWRNORM)

2)select

select系统调用用于多路监控,当没有一个文件满足要求时,select将阻塞调用进程

int select(int maxfd,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,const struct timeval *timeout)

返回值:

正常情况下返回满足要求的文件描述符个数,

超时返回0

出错或中断返回-1

使用方法:

将要监控的文件添加到文件描述符集

调用select开始监控

判断文件是否发生变化

文件描述符操作集:

#include <sys/select.h>

void FD_SET(inf fd,fd_set *fdset); //将文件描述符fd添加到文件描述符集fdset中

void FD_CLR(inf fd,fd_set *fdset);//将文件描述符集fdset中清除文件描述符fd

void FD_ZERO(fd_set *fdset);//清空文件描述符集fdset

void FD_ISSET(inf fd,fd_set *fdset);//检测文件描述符集fdset中的文件fd是否发生了变化

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值