<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 打通linux的tty驅動(dòng)的數據鏈路

打通linux的tty驅動(dòng)的數據鏈路

作者: 時(shí)間:2016-10-08 來(lái)源:網(wǎng)絡(luò ) 收藏

一、首先把tty驅動(dòng)在linux中的分層結構理清楚:

本文引用地址:http://dyxdggzs.com/article/201610/305940.htm
.

自上而下分為T(mén)TY核心層、TTY線(xiàn)路規程、TTY驅動(dòng)。

二、TTY核心層與線(xiàn)路規程層分析

用戶(hù)空間的程序直接對tty核心層進(jìn)行讀寫(xiě)等相關(guān)操作,在tty_io.c中:

int__init tty_init(void)

{

cdev_init(tty_cdev,tty_fops);

if(cdev_add(tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||

register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, /dev/tty) 0)

panic(Couldn'tregister /dev/tty drivern);

device_create(tty_class,NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, tty);

………

以上的一段初始化代碼可以獲取以下信息:

注冊了一個(gè)字符驅動(dòng),用戶(hù)空間操作對應到tty_fops結構體里的函數:

staticconst struct file_operations tty_fops = {

。llseek =no_llseek,

。read =tty_read,

。write =tty_write,

。poll =tty_poll,

。unlocked_ioctl =tty_ioctl,

。compat_ioctl =tty_compat_ioctl,

。open =tty_open,

。release =tty_release,

。fasync =tty_fasync,

};

對于字符設備驅動(dòng),我們知道,讀寫(xiě)操作一一對應于fops.

tty_open:

static int tty_open(struct inode *inode, struct file *filp)

{

int index;

dev_tdevice = inode->i_rdev;

structtty_driver *driver;

……

driver= get_tty_driver(device, index);

……

tty= tty_init_dev(driver, index, 0);

……

retval= tty_add_file(tty, filp);

……

if(tty->ops->open)

retval= tty->ops->open(tty, filp);

get_tty_driver是根據設備號device,通過(guò)查找tty_drivers全局鏈表來(lái)查找tty_driver.

tty_init_dev是初始化一個(gè)tty結構體:

tty->driver= driver;

tty->ops= driver->ops;

并建立線(xiàn)路規程:

ldops= tty_ldiscs[N_TTY];

ld->ops= ldops;

tty->ldisc= ld;

其實(shí)tty_ldiscs[N_TTY]在console_init中確定,該函數在內核啟動(dòng)的時(shí)候調用。

tty_register_ldisc(N_TTY,tty_ldisc_N_TTY);

則:tty_ldiscs[N_TTY]=tty_ldisc_N_TTY;

struct tty_ldisc_ops tty_ldisc_N_TTY = {

。magic = TTY_LDISC_MAGIC,

。name = n_tty,

。open = n_tty_open,

。close = n_tty_close,

。flush_buffer = n_tty_flush_buffer,

。chars_in_buffer= n_tty_chars_in_buffer,

。read = n_tty_read,

。write = n_tty_write,

。ioctl = n_tty_ioctl,

。set_termios = n_tty_set_termios,

。poll = n_tty_poll,

。receive_buf = n_tty_receive_buf,

。write_wakeup = n_tty_write_wakeup

};

tty_add_file主要是將tty保存到file的私有變量private_data中。

tty->ops->open的調用,實(shí)則上就是應用driver->ops->open.這樣,我們就從tty核心層到tty驅動(dòng)層了。

tty_write:

static ssize_t tty_write(struct file *file, const char __user *buf,

size_t count, loff_t *ppos)

{

………

ld= tty_ldisc_ref_wait(tty);

if(!ld->ops->write)

ret= -EIO;

else

ret= do_tty_write(ld->ops->write, tty, file, buf, count);

………

}

從以上這個(gè)函數里,可以看到tty_write調用路線(xiàn)規程的write函數,所以,我們來(lái)看ldisc中的write函數是怎樣的。經(jīng)過(guò)一些操作后,最終調用:

tty->ops->flush_chars(tty);

tty->ops->write(tty,b, nr);

顯然,這兩個(gè)函數,都調用了tty_driver操作函數,因為在之前的tty_open函數中有了tty->ops=driver-> ops這樣的操作。那么這個(gè)tty_driver是怎樣的呢,在TTY系統中,tty_driver是需要在驅動(dòng)層注冊的。注冊的時(shí)候就初始化了ops, 也就是說(shuō),接下來(lái)的事情要看tty_driver的了。

tty_read:

static ssize_t tty_read(struct file *file, char __user *buf, size_t count,

loff_t *ppos)

{

………

ld= tty_ldisc_ref_wait(tty);

if(ld->ops->read)

i= (ld->ops->read)(tty, file, buf, count);

else

i= -EIO;

……

}

像tty_write的一樣,在tty_read里,也調用了線(xiàn)路規程的對應read函數。不同的是,這個(gè)read沒(méi)有調用tty_driver里ops的read,而是這樣:

uncopied= copy_from_read_buf(tty, b, nr);

uncopied+= copy_from_read_buf(tty, b, nr);

從函數名來(lái)看copy_from_read_buf,就是從read_buf這個(gè)緩沖區拷貝數據。實(shí)際上是在tty->read_buf的末尾 tty->read_tail中讀取數據。那么read_buf中的數據是怎么來(lái)的呢?猜想,那肯定是tty_driver干的事了。

tty_ioctl:

long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

{

……

switch(cmd) {

case… …… :


上一頁(yè) 1 2 3 下一頁(yè)

關(guān)鍵詞:

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>