<深入浅出> tty pty读写大体流程拾遗

来源:互联网 发布:炒股模拟软件新手 编辑:程序博客网 时间:2024/06/06 15:44

n_tty.c --- implements the N_TTY line discipline.

 

vfs_write
file->f_op->write
struct file_operations tty_fops={
 .write  = tty_write,
}

ld = tty_ldisc_ref_wait(tty);
do_tty_write(ld->write)


copy_from_user(tty->write_buf, buf, size)
(ld->write)(tty, file, tty->write_buf, size);

struct tty_ldisc tty_ldisc_N_TTY = {
  write_chan,  /* write */
}

add_wait_queue(&tty->write_wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);

tty->driver->write
schedule();


最终的写实现是tty_driver.write

而这个tty_driver可能是serial console以及pty

以pty为例

通过tty_set_operations设置tty_driver的write为pty_write

主设备的tty_struct通过link指向从设备的tty_struct,
struct tty_struct *to = tty->link;
to->ldisc.receive_buf(to, buf, NULL, c);


n_tty_receive_buf(buf)

memcpy(tty->read_buf + tty->read_head, cp, i);

if (waitqueue_active(&tty->read_wait))
   wake_up_interruptible(&tty->read_wait);

唤醒阻塞的读者

如果从设备阻塞在read上

vfs_read

file->f_op->read

struct file_operations tty_fops={
.read  = tty_read,
}
tty_read:
lock_kernel();
(ld->read)(tty,file,buf,count);
unlock_kernel();

struct tty_ldisc tty_ldisc_N_TTY = {
read_chan,  /* read */
}

read_chan:
add_wait_queue(&tty->read_wait, &wait);
schedule_timeout(timeout);
之前pty_write已经把数据从write_buf写到从设备的read_buf了

c = tty->read_buf[tty->read_tail];
put_user(c, b++)
这样就把从设备read_buf里的数据拷贝给用户态了

最后
check_unthrottle(tty);
tty->driver->unthrottle(tty); 这里唯一用到tty_driver
pty_unthrottle
tty_wakeup(o_tty);
wake_up_interruptible(&tty->write_wait);

这里唤醒写者