接着分析tty_read和tty_write函数。
0873 static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
0874 loff_t *ppos)
0875 {
0876 int i;
0877 struct tty_struct *tty;
0878 struct inode *inode;
0879 struct tty_ldisc *ld;
0880
0881 tty = (struct tty_struct *)file->private_data;
0882 inode = file->f_path.dentry->d_inode;
0883 if (tty_paranoia_check(tty, inode, "tty_read"))
0884 return -EIO;
0885 if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
0886 return -EIO;
0887
0888 /* We want to wait for the line discipline to sort out in this
0889 situation */
0890 ld = tty_ldisc_ref_wait(tty);
0891 if (ld->ops->read)
0892 i = (ld->ops->read)(tty, file, buf, count);
0893 else
0894 i = -EIO;
0895 tty_ldisc_deref(ld);
0896 if (i > 0)
0897 inode->i_atime = current_fs_time(inode->i_sb);
0898 return i;
0899 }
如果tty_driver中没有read或tty有错误都会有效性判断失败返回。
第0881行从file->private_data取得tty,这个file->private_data的赋值是在打开设备是进行的。
第0890行tty_ldisc_ref_wait函数如下:
0328 struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
0329 {
0330 struct tty_ldisc *ld;
0331
0332 /* wait_event is a macro */
0333 wait_event(tty_ldisc_wait, (ld = tty_ldisc_try(tty)) != NULL);
0334 return ld;
0335 }
0299 static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty)
0300 {
0301 unsigned long flags;
0302 struct tty_ldisc *ld;
0303
0304 spin_lock_irqsave(&tty_ldisc_lock, flags);
0305 ld = NULL;
0306 if (test_bit(TTY_LDISC, &tty->flags))
0307 ld = get_ldisc(tty->ldisc);
0308 spin_unlock_irqrestore(&tty_ldisc_lock, flags);
0309 return ld;
0310 }
当前进程在tty_ldisc_wait上睡眠,知道tty相应的线路规程存在才被唤醒,并递增ldsic的引用计数。
第0891~0894行,如果线路规程的read操作存在则调用它。线路规程的read函数的实现后面在做分析。
tty_read函数分析完了,十几上比较简单,调用了相应线路规程的read函数。
接着看tty_write函数:
1048 static ssize_t tty_write(struct file *file, const char __user *buf,
1049 size_t count, loff_t *ppos)
1050 {
1051 struct tty_struct *tty;
1052 struct inode *inode = file->f_path.dentry->d_inode;
1053 ssize_t ret;
1054 struct tty_ldisc *ld;
1055
1056 tty = (struct tty_struct *)file->private_data;
1057 if (tty_paranoia_check(tty, inode, "tty_write"))
1058 return -EIO;
1059 if (!tty || !tty->ops->write ||
1060 (test_bit(TTY_IO_ERROR, &tty->flags)))
1061 return -EIO;
1062 /* Short term debug to catch buggy drivers */
1063 if (tty->ops->write_room == NULL)
1064 printk(KERN_ERR "tty driver %s lacks a write_room method.\n",
1065 tty->driver->name);
1066 ld = tty_ldisc_ref_wait(tty);
1067 if (!ld->ops->write)
1068 ret = -EIO;
1069 else
1070 ret = do_tty_write(ld->ops->write, tty, file, buf, count);
1071 tty_ldisc_deref(ld);
1072 return ret;
1073 }
这个函数结构跟tty_read很相似,看到第1070行do_tty_write函数:
0922 static inline ssize_t do_tty_write(
0923 ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char *, size_t),
0924 struct tty_struct *tty,
0925 struct file *file,
0926 const char __user *buf,
0927 size_t count)
0928 {
0929 ssize_t ret, written = 0;
0930 unsigned int chunk;
0931
0932 ret = tty_write_lock(tty, file->f_flags & O_NDELAY);
0933 if (ret < 0)
0934 return ret;
0935
0936 /*
0937 * We chunk up writes into a temporary buffer. This
0938 * simplifies low-level drivers immensely, since they
0939 * don't have locking issues and user mode accesses.
0940 *
0941 * But if TTY_NO_WRITE_SPLIT is set, we should use a
0942 * big chunk-size..
0943 *
0944 * The default chunk-size is 2kB, because the NTTY
0945 * layer has problems with bigger chunks. It will
0946 * claim to be able to handle more characters than
0947 * it actually does.
0948 *
0949 * FIXME: This can probably go away now except that 64K chunks
0950 * are too likely to fail unless switched to vmalloc...
0951 */
0952 chunk = 2048;
0953 if (test_bit(TTY_NO_WRITE_SPLIT, &tty->flags))
0954 chunk = 65536;
0955 if (count < chunk)
0956 chunk = count;
0957
0958 /* write_buf/write_cnt is protected by the atomic_write_lock mutex */
0959 if (tty->write_cnt < chunk) {
0960 unsigned char *buf_chunk;
0961
0962 if (chunk < 1024)
0963 chunk = 1024;
0964
0965 buf_chunk = kmalloc(chunk, GFP_KERNEL);
0966 if (!buf_chunk) {
0967 ret = -ENOMEM;
0968 goto out;
0969 }
0970 kfree(tty->write_buf);
0971 tty->write_cnt = chunk;
0972 tty->write_buf = buf_chunk;
0973 }
0974
0975 /* Do the write .. */
0976 for (;;) {
0977 size_t size = count;
0978 if (size > chunk)
0979 size = chunk;
0980 ret = -EFAULT;
0981 if (copy_from_user(tty->write_buf, buf, size))
0982 break;
0983 ret = write(tty, file, tty->write_buf, size);
0984 if (ret <= 0)
0985 break;
0986 written += ret;
0987 buf += ret;
0988 count -= ret;
0989 if (!count)
0990 break;
0991 ret = -ERESTARTSYS;
0992 if (signal_pending(current))
0993 break;
0994 cond_resched();
0995 }
0996 if (written) {
0997 struct inode *inode = file->f_path.dentry->d_inode;
0998 inode->i_mtime = current_fs_time(inode->i_sb);
0999 ret = written;
1000 }
1001 out:
1002 tty_write_unlock(tty);
1003 return ret;
1004 }
默认没次写2K数据。如果设置了TTY_NO_WRITE_SPLIT则一次写65536的数据。
tty->write_buf是写操作的临时缓存区。即将用户空的数据暂时存放到这里。
tty->write_cnt是临时缓存区的大小。
然后将用户空间的数据copy到临时缓存区,调用规程的write操作完成写操作。
最后再更新设备结点的时间戳。
tty_write函数就分析到这里。
tty_fops的其它操作有兴趣的读者请自行分析代码。