Linux终端设备驱动文档格式.docx

上传人:b****5 文档编号:17467662 上传时间:2022-12-01 格式:DOCX 页数:12 大小:33KB
下载 相关 举报
Linux终端设备驱动文档格式.docx_第1页
第1页 / 共12页
Linux终端设备驱动文档格式.docx_第2页
第2页 / 共12页
Linux终端设备驱动文档格式.docx_第3页
第3页 / 共12页
Linux终端设备驱动文档格式.docx_第4页
第4页 / 共12页
Linux终端设备驱动文档格式.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

Linux终端设备驱动文档格式.docx

《Linux终端设备驱动文档格式.docx》由会员分享,可在线阅读,更多相关《Linux终端设备驱动文档格式.docx(12页珍藏版)》请在冰豆网上搜索。

Linux终端设备驱动文档格式.docx

字符串信息。

这样,登录程序与telnet程序就通过伪终端进行通信。

通过使用适当的软件,可以把2个或多个伪终端设备连接到同一个物理串行端口上。

3.控制台终端(/dev/ttyn,/dev/console如果当前进程有控制终端(ControllingTerminal)的话,那么/dev/tty就是当前进程的控制终端的设备特殊文件。

可以使用命令"

ps–ax"

来查看进程与哪个控制终端相连使用命令"

tty"

可以查看它具体对应哪个实际终端设备。

/dev/tty有些类似于到实际所使用终端设备的一个联接。

在UNIX系统中,计算机显示器通常被称为控制台终端(Console)。

它仿真了类型为Linux的一种终端(TERM=Linux),并且有一些设备特殊文件与之相关联:

tty0、tty1、tty2等。

当用户在控制台上登录时,使用的是tty1。

使用Alt+[F1-F6]组合键时,我们就可以切换到tty2、tty3等上面去。

tty1–tty6等称为虚拟终端,而tty0则是当前所使用虚拟终端的一个别名,系统所产生的信息会发送到该终端上。

因此不管当前正在使用哪个虚拟终端,系统信息都会发送到控制台终端上。

用户可以登录到不同的虚拟终端上去,因而可以让系统同时有几个不同的会话期存在。

只有系统或超级用户root可以向/dev/tty0进行写操作。

在Linux中,可以在系统启动命令行里指定当前的输出终端,格式如下:

console=device,optionsdevice指代的是终端设备,可以是tty0(前台的虚拟终端)、ttyX(第X个虚拟终端)、ttySX(第X个串口)、lp0(第一个并口)等。

options指代对device进行的设置,它取决于具体的设备驱动。

对于串口设备,参数用来定义为:

波特率、校验位、位数,格式为BBBBPN,其中BBBB表示波特率,P表示校验(n/o/e),N表示位数,默认options是9600n8。

用户可以在内核命令行中同时设定多个终端,这样输出将会在所有的终端上显示,而当用户调用open()打开/dev/console时,最后一个终端将会返回作为当前值。

例如:

console=ttyS1,9600console=tty0定义了2个终端,而调用open()打开/dev/console时,将使用虚拟终端tty0。

但是内核消息会在tty0VGA虚拟终端和串口ttyS1上同时显示。

通过查看/proc/tty/drivers文件可以获知什么类型的tty设备存在以及什么驱动被加载到内核,这个文件包括一个当前存在的不同tty驱动的列表,包括驱动名、缺省的节点名、驱动的主编号、这个驱动使用的次编号范围,以及tty驱动的类型。

例如,下面给出了一个/proc/tty/drivers文件的例子。

14.2终端设备驱动结构Linux内核中tty的层次结构下图所示,包含tty核心、tty线路规程和tty驱动。

tty线路规程的工作是以特殊的方式格式化从一个用户或者硬件收到的数据,这种格式化常常采用一个协议转换的形式,例如PPP和Bluetooth。

tty设备发送数据的流程为:

tty核心从一个用户获取将要发送给一个tty设备的数据,tty核心将数据传递给tty线路规程驱动,接着数据被传递到tty驱动,tty驱动将数据转换为可以发送给硬件的格式。

接收数据的流程为:

从tty硬件接收到的数据向上交给tty驱动,进入tty线路规程驱动,再进入tty核心,在这里它被一个用户获取。

尽管大多数时候tty核心和tty之间的数据传输会经历tty线路规程的转换,但是tty驱动与tty核心之间也可以直接传输数据。

tty设备驱动

在linux内核中已经实现了tty驱动层,

图14.2显示了与tty相关的主要源文件及数据的流向。

tty_io.c定义了tty设备通用的file_operations结构体并实现了接口函数tty_register_driver()用于注册tty设备,它会利用fs/char_dev.c提供的接口函数注册字符设备,与具体设备对应的tty驱动将实现tty_driver结构体中的成员函数。

同时tty_io.c也提供了tty_register_ldisc()接口函数用于注册线路规程,n_tty.c文件则实现了tty_disc结构体中的成员。

fs/char_dev.ctty_io.cxxx_tty.cn_tty.c

/dev/ttyS0DB9

注册字符设备

Struct_fileoperationstty_register_driver()

Structtty_drivertty_register_ldiscStructtty_disc

图14.2tty主要源文件关系及数据流向

从图14.2可以看出,特定tty设备驱动的主体工作是填充tty_driver结构体中的成员,实现其中的成员函数,tty_driver结构体的定义如代码清单14.1。

代码清单14.1tty_driver结构体1structtty_driver2{3intmagic;

4structcdevcdev;

/*对应的字符设备cdev*/5structmodule*owner;

/*这个驱动的模块拥有者*/6constchar*driver_name;

7constchar*devfs_name;

8constchar*name;

/*设备名*/9intname_base;

/*offsetofprintedname*/10intmajor;

/*主设备号*/11intminor_start;

/*开始次设备号*/12intminor_num;

/*设备数量*/13intnum;

/*被分配的设备数量*/14shorttype;

/*tty驱动的类型*/15shortsubtype;

/*tty驱动的子类型*/16structtermiosinit_termios;

/*初始线路设置*/17intflags;

/*tty驱动标志*/18intrefcount;

/*引用计数(针对可加载的tty驱动)*/19structproc_dir_entry*proc_entry;

/*/proc文件系统入口*/20structtty_driver*other;

/*仅对PTY驱动有意义*/21.22/*接口函数*/23int(*open)(structtty_struct*tty,structfile*filp);

24void(*close)(structtty_struct*tty,structfile*filp);

25int(*write)(structtty_struct*tty,constunsignedchar*buf,intcount);

26void(*put_char)(structtty_struct*tty,unsignedcharch);

27void(*flush_chars)(structtty_struct*tty);

28int(*write_room)(structtty_struct*tty);

29int(*chars_in_buffer)(structtty_struct*tty);

30int(*ioctl)(structtty_struct*tty,structfile*file,unsignedintcmd,31unsignedlongarg);

32void(*set_termios)(structtty_struct*tty,structtermios*old);

33void(*throttle)(structtty_struct*tty);

34void(*unthrottle)(structtty_struct*tty);

35void(*stop)(structtty_struct*tty);

36void(*start)(structtty_struct*tty);

37void(*hangup)(structtty_struct*tty);

38void(*break_ctl)(structtty_struct*tty,intstate);

39void(*flush_buffer)(structtty_struct*tty);

40void(*set_ldisc)(structtty_struct*tty);

41void(*wait_until_sent)(structtty_struct*tty,inttimeout);

42void(*send_xchar)(structtty_struct*tty,charch);

43int(*read_proc)(char*page,char*start,off_toff,intcount,int*eof,44void*data);

45int(*write_proc)(structfile*file,constchar__user*buffer,unsignedlong46count,void*data);

47int(*tiocmget)(structtty_struct*tty,structfile*file);

48int(*tiocmset)(structtty_struct*tty,structfile*file,unsignedintset,49unsignedintclear);

5051structlist_headtty_drivers;

52};

tty_driver结构体中的magic表示给这个结构体的"

幻数"

,设为TTY_DRIVER_MAGIC,在alloc_tty_driver()函数中被初始化。

name与driver_name的不同在于后者表示驱动的名字,用在/proc/tty和sysfs中,而前者表示驱动的设备节点名。

type与subtype描述tty驱动的类型和子类型,subtype的值依赖于type,type成员的可能值为TTY_DRIVER_TYPE_SYSTEM(由tty子系统内部使用,subtype应当设为SYSTEM_TYPE_TTY、SYSTEM_TYEP_CONSOLE、SYSTEM_TYPE_SYSCONS或SYSTEM_TYPE_SYSPTMX,这个类型不应当被任何常规tty驱动使用)、TTY_DRIVER_TYPE_CONSOLE(仅被控制台驱动使用)、TTY_DRIVER_TYPE_SERIAL(被任何串行类型驱动使用,subtype应当设为SERIAL_TYPE_NORMAL或SERIAL_TYPE_CALLOUT)、TTY_DRIVER_TYPE_PTY(被伪控制台接口pty使用,此时subtype需要被设置为PTY_TYPE_MASTER或PTY_TYPE_SLAVE)。

init_termios为初始线路设置,为一个termios结构体,这个成员被用来提供一个线路设置集合。

termios用于保存当前的线路设置,这些线路设置控制当前波特率、数据大小、数据流控设置等,这个结构体包含tcflag_tc_iflag(输入模式标志)、tcflag_tc_oflag(输出模式标志)、tcflag_tc_cflag(控制模式标志)、tcflag_tc_lflag(本地模式标志)、cc_tc_line(线路规程类型)、cc_tc_cc[NCCS](一个控制字符数组)等成员。

驱动会使用一个标准的数值集初始化这个成员,它拷贝自tty_std_termios变量,tty_std_termos在tty核心中的定义如代码清单14.2。

代码清单14.2tty_std_termios变量1structtermiostty_std_termios=2{3.c_iflag=ICRNL|IXON,/*输入模式*/4.c_oflag=OPOST|ONLCR,/*输出模式*/5.c_cflag=B38400|CS8|CREAD|HUPCL,/*控制模式*/6.c_lflag=ISIG|ICANON|ECHO|ECHOE|ECHOK|7ECHOCTL|ECHOKE|IEXTEN,/*本地模式*/8.c_cc=INIT_C_CC/*控制字符,用来修改终端的特殊字符映射*/9};

tty_driver结构体中的major、minor_start、minor_num表示主设备号、次设备号及可能的次设备数,name表示设备名(如ttyS),第23~49行的函数指针实际和tty_operations结构体等同,它们通常需在特定设备tty驱动模块初始化函数中被赋值。

put_char()为单字节写函数,当单个字节被写入设备时这个函数被tty核心调用,如果一个tty驱动没有定义这个函数,将使用count参数为1的write()函数。

flush_chars()与wait_until_sent()函数都用于刷新数据到硬件。

write_room()指示有多少缓冲区空闲,chars_in_buffer()指示缓冲区中包含的数据数。

当ioctl

(2)在设备节点上被调用时,ioctl()函数将被tty核心调用。

当设备的termios设置被改变时,set_termios()函数将被tty核心调用。

throttle()、unthrottle()、stop()和start()为数据抑制函数,这些函数用来帮助控制tty核心的输入缓存。

当tty核心的输入缓冲满时,throttle()函数将被调用,tty驱动试图通知设备不应当发送字符给它。

当tty核心的输入缓冲已被清空时,unthrottle()函数将被调用暗示设备可以接收数据。

stop()和start()函数非常像throttle()和unthrottle()函数,但它们表示tty驱动应当停止发送数据给设备以及恢复发送数据。

当tty驱动挂起tty设备时,hangup()函数被调用,在此函数中进行相关的硬件操作。

当tty驱动要在RS-232端口上打开或关闭线路的BREAK状态时,break_ctl()线路中断控制函数被调用。

如果state状态设为-1,BREAK状态打开,如果状态设为0,BREAK状态关闭。

如果这个函数由tty驱动实现,而tty核心将处理TCSBRK、TCSBRKP、TIOCSBRK和TIOCCBRK这些ioctl命令。

flush_buffer()函数用于刷新缓冲区并丢弃任何剩下的数据。

set_ldisc()函数用于设置线路规程,当tty核心改变tty驱动的线路规程时这个函数被调用,这个函数通常不需要被驱动定义。

send_xchar()为X-类型字符发送函数,这个函数用来发送一个高优先级XON或者XOFF字符给tty设备,要被发送的字符在第2个参数ch中指定。

read_proc()和write_proc()为/proc读和写函数。

tiocmget()函数用于获得tty设备的线路设置,对应的tiocmset()用于设置tty设备的线路设置,参数set和clear包含了要设置或者清除的线路设置。

Linux内核提供了一组函数用于操作tty_driver结构体及tty设备,包括:

分配tty驱动structtty_driver*alloc_tty_driver(intlines);

这个函数返回tty_driver指针,其参数为要分配的设备数量,line会被赋值给tty_driver的num成员,例如:

xxx_tty_driver=alloc_tty_driver(XXX_TTY_MINORS);

if(!

xxx_tty_driver)//分配失败return-ENOMEM;

tty驱动inttty_register_driver(structtty_driver*driver);

tty驱动成功时返回0,参数为由alloc_tty_driver()分配的tty_driver结构体指针,例如:

retval=tty_register_driver(xxx_tty_driver);

if(retval)//注册失败{printk(KERN_ERR"

failedtoregistertinyttydriver"

);

put_tty_driver(xxx_tty_driver);

returnretval;

}注销tty驱动inttty_unregister_driver(structtty_driver*driver);

这个函数与tty_register_driver()对应,tty驱动最终会调用上述函数注销tty_driver。

tty设备voidtty_register_device(structtty_driver*driver,unsignedindex,structdevice*device);

仅有tty_driver是不够的,驱动必须依附于设备,tty_register_device()函数用于注册关联于tty_driver的设备,index为设备的索引(范围是0~driver-num),如:

for(i=0;

iXXX_TTY_MINORS;

++i)tty_register_device(xxx_tty_driver,i,NULL);

注销tty设备voidtty_unregister_device(structtty_driver*driver,unsignedindex);

上述函数与tty_register_device()对应,用于注销tty设备,其使用方法如:

++i)tty_unregister_device(xxx_tty_driver,i);

设置tty驱动操作voidtty_set_operations(structtty_driver*driver,structtty_operations*op);

上述函数会将tty_operations结构体中的函数指针拷贝给tty_driver对应的函数指针,在具体的tty驱动中,通常会定义1个设备特定的tty_operations,tty_operations的定义如代码清单14.3。

tty_operations中的成员函数与tty_driver中的同名成员函数意义完全一致,因此,这里不再赘述。

代码清单14.3tty_operations结构体1structtty_operations2{3int(*open)(structtty_struct*tty,structfile*filp);

4void(*close)(structtty_struct*tty,structfile*filp);

5int(*write)(structtty_struct*tty,6constunsignedchar*buf,intcount);

7void(*put_char)(structtty_struct*tty,unsignedcharch);

8void(*flush_chars)(structtty_struct*tty);

9int(*write_room)(structtty_struct*tty);

10int(*chars_in_buffer)(structtty_struct*tty);

11int(*ioctl)(structtty_struct*tty,structfile*file,12unsignedintcmd,unsignedlongarg);

13void(*set_termios)(structtty_struct*tty,structtermios*old);

14void(*throttle)(structtty_struct*tty);

15void(*unthrottle)(structtty_struct*tty);

16void(*stop)(structtty_struct*tty);

17void(*start)(structtty_struct*tty);

18void(*hangup)(structtty_struct*tty);

19void(*break_ctl)(structtty_struct*tty,intstate);

20void(*flush_buffer)(structtty_struct*tty);

21void(*set_ldisc)(structtty_struct*tty);

22void(*wait_until_sent)(structtty_struct*tty,inttimeout);

23void(*send_xchar)(structtty_struct*tty,charch);

24int(*read_proc)(char*page,char*start,off_toff,25intcount,int*eof,void*data);

26int(*write_proc)(structfile*file,constchar__user*buffer,27unsignedlongcount,void*data);

28int(*tiocmget)(structtty_struct*tty,structfile*file);

29int(*tiocmset)(structtty_struct*tty,structfile*file,30unsignedintset,unsignedintclear);

31};

终端设备驱动都围绕tty_driver结构体而展开,一般而言,终端设备驱动应包含如下组成

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 小学教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1