首先需要说明的是,这篇文章是我根据lanlovehua的博客http://blog.chinaunix.net/uid-21273878-id-1828727.html与《LDD3》中的TTY驱动程序这章整理而成的。
一、tty设备的数据流通图
tty设备有三层:tty核心、tty线路规程、tty驱动。我们写驱动只负责最底层的tty驱动,线路规程的设置也是在底层的tty驱动,tty核心是封装好的。
用户空间主要是通过设备文件同tty核心交互,而tty核心根据用户空间的操作再选择跟tty线路规程或者tty驱动交互,例:设置硬件的ioctl指令就直接交给tty驱动处理,read和write操作交给tty线路规程处理。
二、TTY驱动怎么没有read函数
主要是因为输入设备和输出设备不一样。由于这样的原因,tty驱动层和tty的线路规程层都有一个缓冲区(因为tty核心只能从tty线路规程层的缓冲区读取数据,所以tty线路规程层也需要一个缓冲区)。
三、驱动程序tiny_tty.c
点击(此处)折叠或打开
四、测试程序
点击(此处)折叠或打开
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <unistd.h>
-
#include <fcntl.h>
-
#include <termios.h>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
-
#define max_buffer_size 100 /*recv buffer size*/
-
-
-
int open_serial(int k)
-
{
-
char pathname[20] = {0};
-
int ret;
-
-
sprintf(pathname, "/dev/ttty%d", k);
-
ret = open(pathname, O_RDWR|O_NOCTTY);
-
if(ret == -1)
-
{
-
perror("open error");
-
exit(-1);
-
}
-
else
-
printf("Open %s success\n", pathname);
-
-
return ret;
-
}
-
-
int main()
-
{
-
int fd;
-
ssize_t n;
-
char recv[max_buffer_size] = {0};
-
struct termios opt;
-
-
fd = open_serial(0); /*open device 0*/
-
-
tcgetattr(fd, &opt);
-
cfmakeraw(&opt);
-
tcsetattr(fd, TCSANOW, &opt);
-
-
-
printf("ready for receiving data...\n");
-
n = read(fd, recv, sizeof(recv));
-
if(n == -1)
-
{
-
perror("read error");
-
exit(-1);
-
}
-
-
printf("The data received is %s", recv);
-
if(close(fd) == -1)
-
perror("close error");
-
-
return 0;
- }
五、测试结果
用户测试信息:
dmesg信息: