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

本文详细探讨了Linux系统中从tty核心层到UART驱动的write操作流程,涉及tty_write()、do_tty_write()、n_tty_write()、uart_write()以及serial8250_start_tx()等关键步骤。讲解了数据如何从核心层经过线路规程和驱动层,最终到达UART端口的输出寄存器。此外,还介绍了TTY_NO_WRITE_SPLIT标志对数据块大小的影响以及数据从用户空间到驱动缓存的拷贝过程。
摘要由CSDN通过智能技术生成

从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();
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值