Linux tty驱动学习 - UART驱动的write操作流程

从tty核心层到最后把数据写入到硬件,整个操作流程如下:tty_write() -> do_tty_write() -> n_tty_write() -> uart_write() -> serial8250_start_tx() -> serial_out()。也就是从tty核心层到线路规程,然后到tty驱动层,再到UART驱动层,最后到UART端口的输出寄存器中。

首先看tty核心的写操作tty_write(),它从file的私有数据中得到tty_struct,再根据tty_struct获得对应的线路规程ld,最后以ld->ops->write为参数调用do_tty_write()。do_tty_write主要对要写入的数据块大小进行处理,然后调用作为参数传递进来的线路规程写函数来写数据到tty驱动层。发送到tty驱动层的数据块大小chunk初始化为2048,但是如果设置了TTY_NO_WRITE_SPLIT标志,则设为65536,即64K大小。如果tty核心层处理的数据大小tty->write_cnt小于chunk,则把tty->write_cnt调整为chunk大小,并重新为tty->write_buf申请内存空间。之后把数据从用户空间拷贝到tty->write_buf,然后调用线路规程N_TTY的n_tty_write()函数来进行进一步的操作。

static inline ssize_t do_tty_write(ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char *, size_t),
	struct tty_struct *tty,struct file *file,const char __user *buf,size_t count)
{
	ssize_t ret, written = 0;
	unsigned int chunk;

	ret = tty_write_lock(tty, file->f_flags & O_NDELAY);
	if (ret < 0)
		return ret;

	chunk = 2048;
	if (test_bit(TTY_NO_WRITE_SPLIT, &tty->flags))
		chunk = 65536;
	if (count < chunk)
		chunk = count;

	/* write_buf/write_cnt is protected by the atomic_write_lock mutex */
	if (tty->write_cnt < chunk) {
		unsigned char *buf_chunk;

		if (chunk < 1024)
			chunk = 1024;

		buf_chunk = kmalloc(chunk, GFP_KERNEL);
		if (!buf_chunk) {
			ret = -ENOMEM;
			goto out;
		}
		kfree(tty->write_buf);
		tty->write_cnt = chunk;
		tty->write_buf = buf_chunk;
	}

	/* Do the write .. */
	for (;;) {
		size_t size = count;
		if (size > chunk)
			size = chunk;
		ret = -EFAULT;
		if (copy_from_user(tty->write_buf, buf, size))
			break;
		ret = write(tty, file, tty->write_buf, size);
		if (ret <= 0)
			break;
		written += ret;
		buf += ret;
		count -= ret;
		if (!count)
			break;
		ret = -ERESTARTSYS;
		if (signal_pending(current))
			break;
		cond_resched();
  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值