色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

tty驅動接口分析

嵌入式與Linux那些事 ? 來源:嵌入式與Linux那些事 ? 2023-07-14 12:21 ? 次閱讀

前言

tty這個名稱源于電傳打字節的簡稱,在linux表示各種終端,終端通常都跟硬件相對應。比如對應于輸入設備鍵盤鼠標,輸出設備顯示器的控制終端和串口終端。也有對應于不存在設備的pty驅動。在如此眾多的終端模型之中,linux是怎么將它們統一建模的呢?這就是我們今天要討論的問題。

tty驅動概貌

tty架構如下所示:

08cc06bc-21fc-11ee-962d-dac502259ad0.png

如上圖所示,用戶空間主要是通過系統調用與tty core交互。tty core根據用空間操作的類型再選擇跟line discipline和tty driver交互。

例如,設置硬件的ioctl指令就直接交給tty_driver處理。read和write操作就會交給 line discipline處理。

Line discipline是線路規程的意思。正如它的名字一樣,它表示的是這條終端”線程”的輸入與輸出規范設置。主要用來進行輸入/輸出數據的預處理。

處理之后,就會將數據交給tty driver ,它將字符轉換成終端可以理解的字串。將其傳給終端設備。

值得注意的是,這個架構沒有為tty driver 提供read操作。也就是說tty core 和line discipline都沒有辦法從tty driver里直接讀終端信息。這是因為tty driver對應的hardware并不一定是輸入數據和輸出 數據的共同負載者。

例如控制終端,輸出設備是顯示器,輸入設備是鍵盤。基于這樣的原理。在line discipline中有一個輸入緩存區,并提供了一個名叫receive_buf()的接口函數。對應的終端設備只要調用line discipine的receiver_buf函數,將數據寫入到輸入緩存區就可以了。如果一個設備同時是輸入設備又是輸出設備。那在設備的中斷處理中調用receive_buf()將數據寫入即可.

tty驅動接口分析

tty_init()

/*
*Ok,nowwecaninitializetherestofthettydevicesandcancount
*onmemoryallocations,interruptsetc..
*/
int__inittty_init(void)
{
tty_sysctl_init();
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")

tty_init主要做了以下工作:

初始化 tty 子系統的 sysctl 相關設置,包括注冊 sysctl 參數、創建 sysctl 目錄等。

初始化 tty 設備的字符設備對象,并將其與 tty 設備操作函數 tty_fops 綁定。同時,創建一個名為 "tty" 的 tty 設備節點,并將其設備號設置為 MKDEV(TTYAUX_MAJOR, 0)。

初始化控制臺設備的字符設備對象,并將其添加到字符設備系統中。同時,創建一個名為 "console" 的控制臺設備節點,并將其設備號設置為 MKDEV(TTYAUX_MAJOR, 1)。該控制臺設備節點還將在 sysfs 中創建一個名為 "console" 的目錄,并在該目錄下創建多個屬性文件,用于控制控制臺的一些屬性。

如果內核支持虛擬終端,則初始化虛擬終端。

這里我們看到了熟悉的cdev_init(),device_create()之類的函數,這正是字符設備的創建流程。因此,我們說串口驅動也是一個字符設備驅動。

而在serial8250_init()中,會調用platform_driver_register()去注冊serial8250_isa_driver,在設備樹節點和serial8250_isa_driver name匹配的時候,就會進入probe流程。因此,也可以說串口驅動是總線設備驅動模型。

tty_alloc_driver

/*UseTTY_DRIVER_*flagsbelow*/
#definetty_alloc_driver(lines,flags)
__tty_alloc_driver(lines,THIS_MODULE,flags)

__tty_alloc_driver()用于分配一個 tty 驅動程序的數據結構 struct tty_driver,并對其一些常用字段進行初始化。

/**
*__tty_alloc_driver--allocatettydriver
*@lines:countoflinesthisdrivercanhandleatmost
*@owner:modulewhichisrepsonsibleforthisdriver
*@flags:someofTTY_DRIVER_*flags,willbesetindriver->flags
*
*Thisshouldnotbecalleddirectly,someoftheprovidedmacrosshouldbe
*usedinstead.UseIS_ERRandfriendson@retval.
*/
structtty_driver*__tty_alloc_driver(unsignedintlines,structmodule*owner,
unsignedlongflags)
{
structtty_driver*driver;
unsignedintcdevs=1;
interr;

if(!lines||(flags&TTY_DRIVER_UNNUMBERED_NODE&&lines>1))
returnERR_PTR(-EINVAL);

/*分配一個structtty_driver結構體,并對其中的一些字段進行初始化,包括num、owner、flags等*/
driver=kzalloc(sizeof(structtty_driver),GFP_KERNEL);
if(!driver)
returnERR_PTR(-ENOMEM);

kref_init(&driver->kref);
driver->magic=TTY_DRIVER_MAGIC;
driver->num=lines;
driver->owner=owner;
driver->flags=flags;

/*如果TTY_DRIVER_DEVPTS_MEM標志位沒有被設置,那么函數會分配driver->ttys和driver->termios,否則不需要分配*/
if(!(flags&TTY_DRIVER_DEVPTS_MEM)){
driver->ttys=kcalloc(lines,sizeof(*driver->ttys),
GFP_KERNEL);
driver->termios=kcalloc(lines,sizeof(*driver->termios),
GFP_KERNEL);
if(!driver->ttys||!driver->termios){
err=-ENOMEM;
gotoerr_free_all;
}
}

/*如果TTY_DRIVER_DYNAMIC_ALLOC標志位沒有被設置,那么函數會分配driver->ports,否則不需要分配*/
if(!(flags&TTY_DRIVER_DYNAMIC_ALLOC)){
driver->ports=kcalloc(lines,sizeof(*driver->ports),
GFP_KERNEL);
if(!driver->ports){
err=-ENOMEM;
gotoerr_free_all;
}
cdevs=lines;
}

/*函數會根據lines的值分配相應數量的driver->cdevs*/
driver->cdevs=kcalloc(cdevs,sizeof(*driver->cdevs),GFP_KERNEL);
if(!driver->cdevs){
err=-ENOMEM;
gotoerr_free_all;
}

returndriver;
err_free_all:
kfree(driver->ports);
kfree(driver->ttys);
kfree(driver->termios);
kfree(driver->cdevs);
kfree(driver);
returnERR_PTR(err);
}

tty_register_driver

tty_register_driver用于注冊 tty 驅動程序的,被 tty 驅動程序調用以將自己注冊到內核中。

/*
*Calledbyattydrivertoregisteritself.
*/
inttty_register_driver(structtty_driver*driver)
{
interror;
inti;
dev_tdev;
structdevice*d;

/*確認是否要內核動態分配主設備號*/
if(!driver->major){
/*函數調用alloc_chrdev_region函數來動態分配主設備號,并將分配的主設備號和次設備號保存在driver->major和driver->minor_start字段中*/
error=alloc_chrdev_region(&dev,driver->minor_start,
driver->num,driver->name);
if(!error){
driver->major=MAJOR(dev);
driver->minor_start=MINOR(dev);
}
}else{
/*已經預先分配了主設備號,函數調用register_chrdev_region函數來注冊設備號*/
dev=MKDEV(driver->major,driver->minor_start);
error=register_chrdev_region(dev,driver->num,driver->name);
}
if(errorflags&TTY_DRIVER_DYNAMIC_ALLOC){
/*需要動態分配tty設備號,函數調用tty_cdev_add函數來添加tty設備號,并將每個tty設備的字符設備注冊到內核中*/
error=tty_cdev_add(driver,dev,0,driver->num);
if(error)
gotoerr_unreg_char;
}

mutex_lock(&tty_mutex);
/*將driver添加到鏈表tty_drivers中*/
list_add(&driver->tty_drivers,&tty_drivers);
mutex_unlock(&tty_mutex);

/*判斷TTY_DRIVER_DYNAMIC_DEV標志位是否設置*/
if(!(driver->flags&TTY_DRIVER_DYNAMIC_DEV)){
for(i=0;inum;i++){
/*需要注冊固定的tty設備號,函數在循環中調用tty_register_device函數來注冊每個tty設備號,并將每個tty設備注冊到內核中*/
d=tty_register_device(driver,i,NULL);
if(IS_ERR(d)){
error=PTR_ERR(d);
gotoerr_unreg_devs;
}
}
}
/*注冊/proc/tty/drivers目錄中的信息*/
proc_tty_register_driver(driver);
/*將driver結構體中的flags字段設置為TTY_DRIVER_INSTALLED,表示該驅動程序已經被成功注冊到內核中*/
driver->flags|=TTY_DRIVER_INSTALLED;
return0;

err_unreg_devs:
for(i--;i>=0;i--)
tty_unregister_device(driver,i);

mutex_lock(&tty_mutex);
list_del(&driver->tty_drivers);
mutex_unlock(&tty_mutex);

err_unreg_char:
unregister_chrdev_region(dev,driver->num);
err:
returnerror;
}

tty_register_driver()函數操作比較簡單。就是為tty_driver創建字符設備。然后將字符設備的操作集指定為tty_fops。并且將tty_driver 掛載到tty_drivers鏈表中。這個鏈表中是以設備號為關鍵字找到對應的driver。

特別的。如果沒有定義TTY_DRIVER_DYNAMIC_DEV。還會在sysfs中創建一個類設備。這樣主要是為了udev管理設備。

tty_unregister_device

tty_unregister_device用于注銷一個 tty 設備。該函數的作用是銷毀設備節點和字符設備,以便于釋放與該 tty 設備相關的資源,例如內存和設備文件等.

/**
*tty_unregister_device-unregisterattydevice
*@driver:thettydriverthatdescribesthettydevice
*@index:theindexinthettydriverforthisttydevice
*
*Ifattydeviceisregisteredwithacalltotty_register_device()then
*thisfunctionmustbecalledwhenthettydeviceisgone.
*
*Locking:??
*/

voidtty_unregister_device(structtty_driver*driver,unsignedindex)
{
device_destroy(tty_class,
MKDEV(driver->major,driver->minor_start)+index);
if(!(driver->flags&TTY_DRIVER_DYNAMIC_ALLOC)){
cdev_del(driver->cdevs[index]);
driver->cdevs[index]=NULL;
}
}

tty_unregister_device所做工作如下:

調用 device_destroy 函數來銷毀 tty 設備對應的設備節點。接受兩個參數:第一個參數 tty_class 表示 tty 類,第二個參數是 tty 設備的設備號,其中 MKDEV(driver->major, driver->minor_start) + index 表示 tty 設備的設備號,driver->major 表示 tty 設備的主設備號,driver->minor_start 表示 tty 設備的次設備號的起始值,index 表示 tty 設備的索引

如果該 tty 驅動程序不是動態分配的,則調用 cdev_del 函數來注銷該 tty 設備對應的字符設備。

get_tty_driver

get_tty_driver作用是在用戶空間的應用程序使用 tty 設備時,獲取對應的 tty 驅動程序的信息。

/**
*get_tty_driver-finddeviceofatty
*@dev_t:deviceidentifier
*@index:returnstheindexofthetty
*
*Thisroutinereturnsattydriverstructure,givenadevicenumber
*andalsopassesbacktheindexnumber.
*
*Locking:callermustholdtty_mutex
*/

staticstructtty_driver*get_tty_driver(dev_tdevice,int*index)
{
structtty_driver*p;

/**/
list_for_each_entry(p,&tty_drivers,tty_drivers){
dev_tbase=MKDEV(p->major,p->minor_start);
if(device=base+p->num)
continue;
*index=device-base;
returntty_driver_kref_get(p);
}
returnNULL;
}

首先使用 list_for_each_entry 循環遍歷全局鏈表 tty_drivers,該鏈表中保存了所有已經注冊的 tty 驅動程序。對于每個 tty 驅動程序,函數將其設備號的起始值和結束值計算出來,如果給定設備號不在這個范圍內,則繼續遍歷下一個 tty 驅動程序。

如果給定設備號在某個 tty 驅動程序的范圍內,則計算出該設備號對應的 tty 設備的索引值,并調用 tty_driver_kref_get 函數來獲取該 tty 驅動程序的引用計數。函數返回該 tty 驅動程序的結構體指針,并將找到的 tty 設備的索引值保存到 index 參數中。

需要注意的是,函數在訪問全局鏈表 tty_drivers 時,需要持有互斥鎖 tty_mutex。因為多個應用程序可能同時訪問同一個 tty 驅動程序,如果沒有互斥鎖保護,可能會導致并發問題。

tty_open

從注冊的過程可以看到,所有的操作都會對應到tty_fops中。Open操作對應的操作接口是tty_open(),用于打開一個 tty 設備。函數的作用是在用戶空間的應用程序使用 tty 設備時,打開對應的 tty 設備,并初始化相應的數據結構。

/**
*tty_open-openattydevice
*@inode:inodeofdevicefile
*@filp:filepointertotty
*
*tty_openandtty_releasekeepupthettycountthatcontainsthe
*numberofopensdoneonatty.Wecannotusetheinode-count,as
*differentinodesmightpointtothesametty.
*
*Open-countingisneededforptymasters,aswellasforkeeping
*trackofseriallines:DTRisdroppedwhenthelastclosehappens.
*(Thisisnotdonesolelythroughtty->count,now.-Ted1/27/92)
*
*Thetermiosstateofaptyisresetonfirstopensothat
*settingsdon'tpersistacrossreuse.
*
*Locking:tty_mutexprotectstty,tty_lookup_driverandtty_init_dev.
*tty->countshouldprotecttherest.
*->siglockprotects->signal/->sighand
*
*Note:thetty_unlock/lockcaseswithoutarefareonlysafedueto
*tty_mutex
*/

staticinttty_open(structinode*inode,structfile*filp)
{
structtty_struct*tty;
intnoctty,retval;
structtty_driver*driver=NULL;
intindex;
dev_tdevice=inode->i_rdev;
unsignedsaved_flags=filp->f_flags;

nonseekable_open(inode,filp);

retry_open:
/*分配一個tty結構體*/
retval=tty_alloc_file(filp);
if(retval)
return-ENOMEM;

/*檢查文件的標志位,如果包含O_NOCTTY標志,則禁止將該tty設備設置為控制終端*/
noctty=filp->f_flags&O_NOCTTY;
index=-1;
retval=0;
/*嘗試打開當前的tty設備*/
tty=tty_open_current_tty(device,filp);
if(!tty){
mutex_lock(&tty_mutex);
/*根據設備號來查找對應的tty驅動程序,并初始化該tty設備,將找到的tty驅動程序保存到driver變量中*/
driver=tty_lookup_driver(device,filp,&noctty,&index);
if(IS_ERR(driver)){
retval=PTR_ERR(driver);
gotoerr_unlock;
}

/*checkwhetherwe'rereopeninganexistingtty*/
/*查找對應的tty設備,并將找到的tty設備結構體指針保存到tty變量中*/
tty=tty_driver_lookup_tty(driver,inode,index);
if(IS_ERR(tty)){
retval=PTR_ERR(tty);
gotoerr_unlock;
}

if(tty){
/*如果找到了該tty設備,則需要重新打開該tty設備*/
mutex_unlock(&tty_mutex);
retval=tty_lock_interruptible(tty);
tty_kref_put(tty);/*dropkreffromtty_driver_lookup_tty()*/
if(retval){
if(retval==-EINTR)
retval=-ERESTARTSYS;
gotoerr_unref;
}
retval=tty_reopen(tty);
if(retvaldriver->type==TTY_DRIVER_TYPE_PTY&&
tty->driver->subtype==PTY_TYPE_MASTER)
noctty=1;

tty_debug_hangup(tty,"(ttycount=%d)
",tty->count);

/*調用tty設備的open函數*/
if(tty->ops->open)
retval=tty->ops->open(tty,filp);
else
retval=-ENODEV;
filp->f_flags=saved_flags;

if(retval){
tty_debug_hangup(tty,"error%d,releasing...
",retval);

tty_unlock(tty);/*needtocalltty_releasewithoutBTM*/
tty_release(inode,filp);
if(retval!=-ERESTARTSYS)
returnretval;

if(signal_pending(current))
returnretval;

schedule();
/*
*Needtoresetf_opincaseahanguphappened.
*/
if(tty_hung_up_p(filp))
filp->f_op=&tty_fops;
gotoretry_open;
}
clear_bit(TTY_HUPPED,&tty->flags);


read_lock(&tasklist_lock);
spin_lock_irq(¤t->sighand->siglock);
if(!noctty&&
current->signal->leader&&
!current->signal->tty&&
tty->session==NULL){
/*
*Don'tletaprocessthatonlyhaswriteaccesstothetty
*obtaintheprivilegesassociatedwithhavingattyas
*controllingterminal(beingabletoreopenitwithfull
*accessthrough/dev/tty,beingabletoperformpushback).
*Manydistributionssetthegroupofallttysto"tty"and
*grantwrite-onlyaccesstoallterminalsforsetgidtty
*binaries,whichshouldnotimplyfullprivilegesonallttys.
*
*Thiscouldtheoreticallybreakoldcodethatperformsopen()
*onawrite-onlyfiledescriptor.Inthatcase,itmightbe
*necessarytoalsopermitthisif
*inode_permission(inode,MAY_READ)==0.
*/
if(filp->f_mode&FMODE_READ)
__proc_set_tty(tty);
}
spin_unlock_irq(¤t->sighand->siglock);
read_unlock(&tasklist_lock);
tty_unlock(tty);
return0;
err_unlock:
mutex_unlock(&tty_mutex);
err_unref:
/*afterlockstoavoiddeadlock*/
if(!IS_ERR_OR_NULL(driver))
tty_driver_kref_put(driver);
err_file:
tty_free_file(filp);
returnretval;
}

函數所作工作如下:

在打開 tty 設備時,該函數會檢查文件的標志位,如果包含 O_NOCTTY 標志,則禁止將該 tty 設備設置為控制終端。這是因為如果一個進程打開一個 tty 設備并將其設置為控制終端,其他進程就無法再將該 tty 設備設置為控制終端,這可能會導致一些問題。

如果打開當前的 tty 設備失敗,則需要根據設備號來查找對應的 tty 驅動程序,并初始化該 tty 設備。在查找 tty 驅動程序時,需要調用 tty_lookup_driver 函數來查找對應的 tty 驅動程序,并將找到的 tty 驅動程序保存到 driver 變量中。如果找不到對應的 tty 驅動程序,則返回錯誤碼。

如果找到了對應的 tty 驅動程序,則調用 tty_driver_lookup_tty 函數來查找對應的 tty 設備,并將找到的 tty 設備結構體指針保存到 tty 變量中。如果找到了該 tty 設備,則需要重新打開該 tty 設備。否則,需要初始化該 tty 設備。在初始化 tty 設備時,需要調用 tty_init_dev 函數來為該 tty 設備分配一個 tty 結構體,并對其進行初始化。

在打開 tty 設備之后,函數會調用 tty_add_file 函數將該 tty 設備與文件結構體相關聯。此外,如果該 tty 設備是一個偽終端主設備,則需要將 noctty 標志設置為 1。

最后,函數會調用 tty 設備的 open 函數,如果存在的話,來進行一些特定的操作。如果 open 函數返回錯誤碼,則需要釋放該 tty 設備并返回錯誤碼。如果 open 函數返回 -ERESTARTSYS,則需要重新打開該 tty 設備。如果有中斷發生,也需要重新打開該 tty 設備。

tty_write

tty_write()作用是將用戶數據寫入 tty 設備,并通過線路規則(line discipline)進行處理。

線路規則是 tty 設備的一種機制,用于處理和轉換從用戶進程到內核和設備的數據流。在寫入 tty 設備之前,需要獲取該 tty 設備的線路規則,并調用其 write 方法進行處理。

/**
*tty_write-writemethodforttydevicefile
*@file:ttyfilepointer
*@buf:userdatatowrite
*@count:bytestowrite
*@ppos:unused
*
*Writedatatoattydeviceviathelinediscipline.
*
*Locking:
*Locksthelinedisciplineasrequired
*Writestothettydriverareserializedbytheatomic_write_lock
*andarethenprocessedinchunkstothedevice.Thelinediscipline
*writemethodwillnotbeinvokedinparallelforeachdevice.
*/

staticssize_ttty_write(structfile*file,constchar__user*buf,
size_tcount,loff_t*ppos)
{
structtty_struct*tty=file_tty(file);
structtty_ldisc*ld;
ssize_tret;

if(tty_paranoia_check(tty,file_inode(file),"tty_write"))
return-EIO;
if(!tty||!tty->ops->write||
(test_bit(TTY_IO_ERROR,&tty->flags)))
return-EIO;
/*Shorttermdebugtocatchbuggydrivers*/
if(tty->ops->write_room==NULL)
printk(KERN_ERR"ttydriver%slacksawrite_roommethod.
",
tty->driver->name);
ld=tty_ldisc_ref_wait(tty);
if(!ld->ops->write)
ret=-EIO;
else
ret=do_tty_write(ld->ops->write,tty,file,buf,count);
tty_ldisc_deref(ld);
returnret;
}

tty_write()所作工作如下:

首先從文件指針中獲取 tty_struct 數據結構的指針,表示要寫入的 tty 設備。

檢查傳入的 tty_struct 指針是否有效,以及是否有其他進程正在訪問該 tty 設備。如果出現問題,返回輸入/輸出錯誤碼 -EIO。

檢查 tty_struct 指針是否有效、tty 設備是否支持寫操作,以及是否已經出現了輸入/輸出錯誤。如果出現問題,返回輸入/輸出錯誤碼 -EIO。

檢查 tty 設備是否實現了 write_room 方法,如果沒有,則輸出錯誤信息。

獲取 tty 設備的線路規則(line discipline),并等待獲取成功。

檢查線路規則的 write 方法是否存在,如果不存在,返回輸入/輸出錯誤碼 -EIO。否則,調用 do_tty_write 函數,將數據寫入 tty 設備。

釋放線路規則引用計數器。

返回寫入操作的結果,如果寫入成功,則返回寫入的字節數;否則,返回相應的錯誤碼。

tty_read

/**
*tty_read-readmethodforttydevicefiles
*@file:pointertottyfile
*@buf:userbuffer
*@count:sizeofuserbuffer
*@ppos:unused
*
*Performthereadsystemcallfunctiononthisterminaldevice.Checks
*forhungupdevicesbeforecallingthelinedisciplinemethod.
*
*Locking:
*Locksthelinedisciplineinternallywhileneeded.Multiple
*readcallsmaybeoutstandinginparallel.
*/

staticssize_ttty_read(structfile*file,char__user*buf,size_tcount,
loff_t*ppos)
{
inti;
structinode*inode=file_inode(file);
structtty_struct*tty=file_tty(file);
structtty_ldisc*ld;

if(tty_paranoia_check(tty,inode,"tty_read"))
return-EIO;
if(!tty||(test_bit(TTY_IO_ERROR,&tty->flags)))
return-EIO;

/*Wewanttowaitforthelinedisciplinetosortoutinthis
situation*/
ld=tty_ldisc_ref_wait(tty);
if(ld->ops->read)
i=ld->ops->read(tty,file,buf,count);
else
i=-EIO;
tty_ldisc_deref(ld);

if(i>0)
tty_update_time(&inode->i_atime);

returni;
}

tty_read()實現終端設備文件讀操作的函數 。

獲取 tty_struct 結構體、inode 和 line discipline 對象的指針。

調用 tty_paranoia_check() 函數檢查 tty_struct 結構體是否可用。如果檢查失敗,返回 -EIO。

檢查 tty_struct 結構體是否為空或者 TTY_IO_ERROR 標志位已經設置。如果是,則返回 -EIO。

獲取 line discipline 對象的引用,確保它不會在 tty_read() 函數執行期間被卸載。

檢查 line discipline 的 read() 方法是否可用。如果可用,則調用該方法進行讀取操作,并將返回的字節數保存在變量 i 中。如果不可用,返回 -EIO。

釋放 line discipline 的引用。

如果讀取操作成功,調用 tty_update_time() 函數更新 inode 的訪問時間。

返回讀取的字節數。

小結

在這一節里,只對tty的構造做一個分析,具體的比如線路規程的內容我們了解知道就好,這里不做深入分析。

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 顯示器
    +關注

    關注

    21

    文章

    4970

    瀏覽量

    139926
  • Linux
    +關注

    關注

    87

    文章

    11292

    瀏覽量

    209331
  • 串口
    +關注

    關注

    14

    文章

    1551

    瀏覽量

    76428
  • 函數
    +關注

    關注

    3

    文章

    4327

    瀏覽量

    62573

原文標題:【驅動】串口驅動分析(二)-tty core

文章出處:【微信號:嵌入式與Linux那些事,微信公眾號:嵌入式與Linux那些事】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    V-BY-ONE技術優勢分析

    目前接口分析:1.TTL:局限性太大,一般在小屏上面應用較多(7寸以下)2.7寸以上的屏現在的接口有LVDS,eDP,iDP,V-BY-ONE。附件講述一下由THine公司發布的V-BY-ONE接口的技術優勢。需要詳細資料的請電
    發表于 03-14 18:24

    Android系統開發之藍牙開發案例分析

    案例,帶您了解真正的藍牙開發技術。主要涉及:藍牙應用接口,藍牙Framework架構,藍牙設備驅動,藍牙開發技巧及數據處理等要點。1. Android的藍牙框架分析2. Android藍牙應用開發
    發表于 07-24 16:32

    FastCV主要接口分析(第二部分)

    FastCV主要接口分析之二 FastCV為計算機視覺(CV,computer vision)的應用開發者提供了兩個主要功能:提供CV常用的函數庫,其已經進行了優化且可以高效的運行在移動設備上;提供
    發表于 09-21 10:29

    FastCV主要接口分析

    FastCV主要接口分析之一 安裝Hexagon SDK后,會在安裝的主目錄下/Hexagon_SDK/2.0/lib/fastcv/hexagon_Release_v5存在如下文件: 上圖
    發表于 09-21 17:05

    淺析linux UART驅動tty架構

    關于linux UART驅動tty架構的理解
    發表于 07-03 09:55

    高清晰視頻會議終端應用接口分析

    高清晰視頻會議終端應用接口分析 DVI接口與HDMI接口介紹   視頻通訊作為
    發表于 02-21 10:10 ?2217次閱讀

    Xilinx FPGA DDR4接口應用分析

    本內容主要分析了基于FPGA的系統需求,賽靈思UltraScale FPGA DDR4和其他并行接口分析以及針對高性能高度靈活方案的PHY解決方案介紹。
    發表于 08-03 19:37 ?191次下載

    Linux中tty、pty、pts的概念區別

    /tty0的符號鏈接嗎?A: 目前的大多數文本中都稱/dev/console是到/dev/tty0的鏈接(包括《Linux內核源代碼情景分析》),但是這樣說是不確切的。根據內核文檔,在2.1.71之前
    發表于 04-02 14:36 ?1306次閱讀

    MAVLink學習之路05_ MAVLink應用編程接口分析

    MAVLink學習之路05_MAVLink應用編程接口分析
    的頭像 發表于 03-07 16:21 ?5803次閱讀

    常用接口分析,必須要全部掌握

    日常使用手機、電腦以及其他電子產品,免不了要跟各種接口打交道。周末花了些時間查了些資料,并總結自己的實際使用經驗,跟大家聊一聊我們日常使用手機、iPad、電腦、外設中常用到的接口。 ?講明白各種接口
    的頭像 發表于 10-30 09:57 ?491次閱讀

    TYPE C母座引腳接口分析及優勢特點的介紹

    接口分析及優勢特點。 TYPE C母座引腳接口分析 Type C母座一般簡稱有type c、type-c等,其實這些指的都
    發表于 12-18 10:59 ?1.5w次閱讀

    tty.js基于瀏覽器的終端模擬器

    ./oschina_soft/tty.js.zip
    發表于 05-26 14:54 ?1次下載
    <b class='flag-5'>tty</b>.js基于瀏覽器的終端模擬器

    SoC接口技術之低速接口分析(下)

    JTAG協議核心是三個寄存器和TAP狀態機。作為DEBUG的JTAG接口會在DAP中利用旁路寄存器將JTAG協議轉換為APB協議。作為DFT的JTAG接口會直接利用數據寄存器進行邊界掃描。
    的頭像 發表于 04-04 16:08 ?1832次閱讀
    SoC<b class='flag-5'>接口</b>技術之低速<b class='flag-5'>接口分析</b>(下)

    Linux中/dev/tty、/dev/tty0和/dev/console之間的區別在哪?

    在Linux系統中,/dev/tty、/dev/tty0和/dev/console是一些特殊的設備文件,經常用于控制臺和命令行界面的操作。
    的頭像 發表于 06-21 09:06 ?3717次閱讀

    串口驅動分析之serial driver

    前兩節我們介紹串口驅動的框架和tty core部分。這節我們介紹和硬件緊密相關的串口驅動部分。
    的頭像 發表于 09-04 14:23 ?420次閱讀
    串口<b class='flag-5'>驅動</b><b class='flag-5'>分析</b>之serial driver
    主站蜘蛛池模板: 97免费视频在线| 亚欧成人毛片一区二区三区四区| 免费观看男生桶美女私人部位| 色久悠悠无码偷拍自怕| 区产品乱码芒果精品P站在线| 欧美一级情欲片在线| 日本红怡院亚洲红怡院最新| 四虎成人影院| 免费视频xxx| 九九久久国产| 韩日午夜在线资源一区二区| 处初女处夜情视频在线播放| 夫妻性姿势真人做视频| 国产精品亚洲国产三区| 好色美女小雅| 美女也烦恼主题曲| 日日夜夜影院在线播放| 亚洲AV成人无码网天堂| 真实处破女全过程完免费观看| 97成人免费视频| 国产AV麻豆出品在线播放| 果冻传媒MV免费播放在线观看| 国产免费人成在线看视频| 精品人妻伦九区久久AAA片69| 国产无线乱码一区二三区| 久久vs国产综合色| 欧美一夜爽爽爽爽爽爽| 香港成人社区| 网址在线观看你懂我意思吧免费的| 亚洲国产精品自在自线观看| 69精品国产人妻蜜桃国产毛片| 俄罗斯美女性生活| 久99久热只有精品国产99| 欧美亚洲高清国产| 亚洲高清国产拍精品影院| 97午夜伦伦电影理论片| 国产精品乱码一区二区三| 伦理片 qvod| 天天啪免费视频在线看| 最近中文字幕在线看免费完整版| 大胸美女被c|