一、tty_read
对于tty_read这个函数,很多标志我也没有弄得太清楚,但是问题不大,以后有机会在看。我觉得重点是看数据怎么从cdc驱动到通过线路规划到tty,再从tty到用户空间。标志位等东西都是为这一个数据的流程服务的。
static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
ld = tty_ldisc_ref_wait(tty);
if (ld->ops->read)
i = (ld->ops->read)(tty, file, buf, count);
else
i = -EIO;
tty_ldisc_deref(ld);
}
第4行,tty_ldisc_ref_wait获取到ld,这个是open中设置好的线路规划操作函数集。
第6行,利用函数集中的read夺取数据,这个read对应的是n_tty_read。
第9行,唤醒其他的等待获取ld的tty_ldisc_ref_wait
static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
unsigned char __user *buf, size_t nr)
{
while (nr) {
if (!input_available_p(tty, 0)) {}
if (ldata->icanon && !L_EXTPROC(tty)) {
while (nr && ldata->read_cnt) {
c = ldata->read_buf[ldata->read_tail];
ldata->read_tail = ((ldata->read_tail+1) &
(N_TTY_BUF_SIZE-1));
ldata->read_cnt--;
if (tty_put_user(tty, c, b++))
nr--;
}
} else {
uncopied = copy_from_read_buf(tty, &b, &nr);
uncopied += copy_from_read_buf(tty, &b, &nr);
}
}
return retval;
}
1、input_available_p这个函数中调用了tty_flush_to_ldisc(tty)这个是利用队列将cdc中的数据存储到线路规划的缓存中,后面在具体分析。
2、接下来很长一段代码都是从线路规划的read_buf中读取数据,并送到用户空间,分为两种方式,一是一个一个的读取缓存中的数据,一个是