【1】.复习
1. 同步互斥
信号量
互斥体
2. IO模型
阻塞
1. 定义等待队列头初始化
2. 定义等待队列项并初始化
3. 将等待队列项挂在等待队列头上
4. 设置进程状态 --->>> 睡眠态(S / D)
5. 调度
---------(条件满足唤醒)-----------
6. 将等待队列项从等待队列头上移除
7. 设置进程状态 --->>> 运行态(R)
wait_event(wq,condition)
wait_event_interruptible(wq,condition)
非阻塞
O_NONBLOCK & filp -> f_flags
【2】.作业
01
02
【一】、IO多路复用
fs/select.c
SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_set __user *, outp,
fd_set __user *, exp, struct timeval __user *, tvp)
--->>> core_sys_select(n, inp, outp, exp, to);
--->>> do_select(n, &fds, end_time);
--->>> mask = (*f_op->poll)(file, wait);
/***********************************************************************
*返回值:
* 返回0,代表条件不满足
* POLLIN
* POLLOUT
**********************************************************************/
unsigned int demo_poll(struct file *filp, struct poll_table_struct *wait)
{
poll_wait();
return 0;
}
typedef struct poll_table_struct {
poll_queue_proc _qproc;
unsigned long _key;
} poll_table;
/***********************************************************************************
*功能:
*参数:
* @filp file结构体指针
* @wait_address 等待队列头
* @p poll_table *
*返回值:void
**********************************************************************************/
void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
【二】、异步通知
通知机制
条件满足通知(驱动通知应用层进程)
通知 --->>> 信号
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
--------------------------------------------------------------
开启异步通知功能:
int fcntl(int fd,int cmd, ... /* arg */ );
异步通知开关(flags):FASYNC
F_GETFL
F_SETFL
F_SETOWN
--------------------------------------------------------------
fcntl(fd,F_SETFL,FASYNC | fcntl(fd,F_GETFL));
fcntl(fd,F_SETOWN,getpid());
--->>> SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
--->>> do_fcntl(fd, cmd, arg, filp);
--->>> err = setfl(fd, filp, arg);
--->>>
if (((arg ^ filp->f_flags) & FASYNC) && filp->f_op &&filp->f_op->fasync) {
error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0);
if (error < 0)
goto out;
if (error > 0)
error = 0;
}
int (*fasync) (int, struct file *, int); //开启异步通知功能
------------------------------------------------------------------------------------------
int demo_fasync(int fd, struct file *filp, int on)
{
return 0;
}
/***********************************************************************************
*功能: 初始化异步通知结构体,并插入到异步通知队列中
*参数:
* @fd 文件描述符
* @filp file结构体指针
* @on 异步通知开关
* @fapp 异步通知结构体
*返回值:失败返回负数错误码 , 成功返回0
**********************************************************************************/
int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
POLL_IN / POLL_OUT
29) SIGIO
void kill_fasync(struct fasync_struct **fp, int signal, int band)
【三】、GPIO子系统
LED --->> 控制灯
KEY --->> 读取按键值
<linux/gpio.h>
GPIOF_DIR_OUT
GPIOF_DIR_IN
GPIOF_INIT_LOW
GPIOF_INIT_HIGH
GPIOF_OUT_INIT_LOW
GPIOF_OUT_INIT_HIGH
struct gpio {
unsigned gpio; //gpio 号
unsigned long flags; //标志
const char *label; //gpio名字
};
gpio编号:
为GPIO统一编号:
GPIOA0 ~ GPIOA31 (0 ~ 31)
GPIOB0 ~ GPIOB31 (32 ~ 63)
...
/***********************************************************
*请求一个指定的GPIO,如果该gpio没有其他驱动使用,返回真,
*如果有其他驱动使用该GPIO,返回负数错误码
**********************************************************/
int gpio_request(unsigned gpio, const char *label)
void gpio_free(unsigned gpio)
/* 请求gpio ,并设置flags */
int gpio_request_one(unsigned gpio,unsigned long flags, const char *label)
/**************************************************************
*功能:请求一组gpio
*参数:
* @array 结构体数组
* @num 结构体数组元素个数
*************************************************************/
int gpio_request_array(const struct gpio *array, size_t num)
void gpio_free_array(const struct gpio *array, size_t num)
int gpio_direction_input(unsigned gpio) //设置gpio输入模式
int gpio_direction_output(unsigned gpio, int value) //设置gpio输出模式,并设置输出值
int gpio_get_value(unsigned gpio) //获取gpio引脚值
void gpio_set_value(unsigned gpio, int value) //设置gpio引脚值
int gpio_to_irq(unsigned gpio) //根据GPIO号获取中断号
红灯 GPIOA28 --->>> (0*32 + 28)
绿灯 GPIOE13 --->>> (4*32 + 13)
蓝灯 GPIOB12 --->>> (1*32 + 12)