一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

ioctl()函數(shù)

 開花結(jié)果 2010-11-04
本函數(shù)影響由fd參數(shù)引用的一個打開的文件。
#include<unistd.h>
#include<sys/ioctl.h>
int ioctl( int fd, int request, .../* void *arg */ );
返回0:成功    -1:出錯
第三個參數(shù)總是一個指針,但指針的類型依賴于request參數(shù)。
我們可以把和網(wǎng)絡(luò)相關(guān)的請求劃分為6類:
套接口操作
文件操作
接口操作
ARP高速緩存操作
路由表操作
流系統(tǒng)
下表列出了網(wǎng)絡(luò)相關(guān)ioctl請求的request參數(shù)以及arg地址必須指向的數(shù)據(jù)類型:
類別
Request
說明
數(shù)據(jù)類型
SIOCATMARK
SIOCSPGRP
SIOCGPGRP
是否位于帶外標(biāo)記
設(shè)置套接口的進(jìn)程ID或進(jìn)程組ID
獲取套接口的進(jìn)程ID或進(jìn)程組ID
int
int
int
 
FIONBIN
FIOASYNC
FIONREAD
FIOSETOWN
FIOGETOWN
設(shè)置/清除非阻塞I/O標(biāo)志
設(shè)置/清除信號驅(qū)動異步I/O標(biāo)志
獲取接收緩存區(qū)中的字節(jié)數(shù)
設(shè)置文件的進(jìn)程ID或進(jìn)程組ID
獲取文件的進(jìn)程ID或進(jìn)程組ID
int
int
int
int
int
SIOCGIFCONF
SIOCSIFADDR
SIOCGIFADDR
SIOCSIFFLAGS
SIOCGIFFLAGS
SIOCSIFDSTADDR
SIOCGIFDSTADDR
SIOCGIFBRDADDR
SIOCSIFBRDADDR
SIOCGIFNETMASK
SIOCSIFNETMASK
SIOCGIFMETRIC
SIOCSIFMETRIC
SIOCGIFMTU
SIOCxxx
獲取所有接口的清單
設(shè)置接口地址
獲取接口地址
設(shè)置接口標(biāo)志
獲取接口標(biāo)志
設(shè)置點(diǎn)到點(diǎn)地址
獲取點(diǎn)到點(diǎn)地址
獲取廣播地址
設(shè)置廣播地址
獲取子網(wǎng)掩碼
設(shè)置子網(wǎng)掩碼
獲取接口的測度
設(shè)置接口的測度
獲取接口MTU
(還有很多取決于系統(tǒng)的實(shí)現(xiàn))
struct ifconf
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
ARP
SIOCSARP
SIOCGARP
SIOCDARP
創(chuàng)建/修改ARP表項(xiàng)
獲取ARP表項(xiàng)
刪除ARP表項(xiàng)
struct arpreq
struct arpreq
struct arpreq
SIOCADDRT
SIOCDELRT
增加路徑
刪除路徑
struct rtentry
struct rtentry
I_xxx
 
 
套接口操作:
明確用于套接口操作的ioctl請求有三個,它們都要求ioctl的第三個參數(shù)是指向某個整數(shù)的一個指針。
SIOCATMARK:    如果本套接口的的度指針當(dāng)前位于帶外標(biāo)記,那就通過由第三個參數(shù)指向的整數(shù)返回一個非0值;否則返回一個0值。POSIX以函數(shù)sockatmark替換本請求。
SIOCGPGRP:       通過第三個參數(shù)指向的整數(shù)返回本套接口的進(jìn)程ID或進(jìn)程組ID,該ID指定針對本套接口的SIGIO或SIGURG信號的接收進(jìn)程。本請求和fcntl的F_GETOWN命令等效,POSIX標(biāo)準(zhǔn)化的是fcntl函數(shù)。
SIOCSPGRP:     把本套接口的進(jìn)程ID或者進(jìn)程組ID設(shè)置成第三個參數(shù)指向的整數(shù),該ID指定針對本套接口的SIGIO或SIGURG信號的接收進(jìn)程,本請求和fcntl的F_SETOWN命令等效,POSIX標(biāo)準(zhǔn)化的是fcntl操作。
文件操作:
以下5個請求都要求ioctl的第三個參數(shù)指向一個整數(shù)。 
FIONBIO:        根據(jù)ioctl的第三個參數(shù)指向一個0或非0值分別清除或設(shè)置本套接口的非阻塞標(biāo)志。本請求和O_NONBLOCK文件狀態(tài)標(biāo)志等效,而該標(biāo)志通過fcntl的F_SETFL命令清除或設(shè)置。 
FIOASYNC:      根據(jù)iocl的第三個參數(shù)指向一個0值或非0值分別清除或設(shè)置針對本套接口的信號驅(qū)動異步I/O標(biāo)志,它決定是否收取針對本套接口的異步I/O信號(SIGIO)。本請求和O_ASYNC文件狀態(tài)標(biāo)志等效,而該標(biāo)志可以通過fcntl的F_SETFL命令清除或設(shè)置。
FIONREAD:     通過由ioctl的第三個參數(shù)指向的整數(shù)返回當(dāng)前在本套接口接收緩沖區(qū)中的字節(jié)數(shù)。本特性同樣適用于文件,管道和終端。
FIOSETOWN:    對于套接口和SIOCSPGRP等效。
FIOGETOWN:    對于套接口和SIOCGPGRP等效。 
接口配置:
得到系統(tǒng)中所有接口由SIOCGIFCONF請求完成,該請求使用ifconf結(jié)構(gòu),ifconf又使用ifreq結(jié)構(gòu),如下所示:
Struct ifconf{
   int ifc_len;                 // 緩沖區(qū)的大小
   union{
         caddr_t ifcu_buf;        // input from user->kernel
         struct ifreq *ifcu_req;    // return of structures returned
     }ifc_ifcu;
}; 
#define  ifc_buf  ifc_ifcu.ifcu_buf    //buffer address
#define  ifc_req  ifc_ifcu.ifcu_req    //array of structures returned
#define  IFNAMSIZ  16
struct ifreq{
    char ifr_name[IFNAMSIZ];           // interface name, e.g., “le0”
    union{
         struct sockaddr ifru_addr;
         struct sockaddr ifru_dstaddr;
         struct sockaddr ifru_broadaddr;
         short ifru_flags;
         int ifru_metric;
         caddr_t ifru_data;
     }ifr_ifru;
};
#define ifr_addr     ifr_ifru.ifru_addr            // address
#define ifr_dstaddr   ifr_ifru.ifru_dstaddr         // otner end of p-to-p link
#define ifr_broadaddr ifr_ifru.ifru_broadaddr    // broadcast address
#define ifr_flags     ifr_ifru.ifru_flags        // flags
#define ifr_metric    ifr_ifru.ifru_metric      // metric
#define ifr_data      ifr_ifru.ifru_data        // for use by interface
再調(diào)用ioctl前我們必須先分撇一個緩沖區(qū)和一個ifconf結(jié)構(gòu),然后才初始化后者。如下圖展示了一個ifconf結(jié)構(gòu)的初始化結(jié)構(gòu),其中緩沖區(qū)的大小為1024,ioctl的第三個參數(shù)指向這樣一個ifconf結(jié)構(gòu)。
ifc_len          1024
Ifc_buf           ---------->緩存
假設(shè)內(nèi)核返回2個ifreq結(jié)構(gòu),ioctl返回時通過同一個ifconf結(jié)構(gòu)緩沖區(qū)填入了那2個ifreq結(jié)構(gòu),ifconf結(jié)構(gòu)的ifc_len成員也被更新,以反映存放在緩沖區(qū)中的信息量
一般來講ioctl在用戶程序中的調(diào)用是:ioctl(int fd,int command, (char*)argstruct)
ioctl調(diào)用與網(wǎng)絡(luò)編程有關(guān)(本文只討論這一點(diǎn)),文件描述符fd實(shí)際上是由socket()系統(tǒng)調(diào)用返回的。參數(shù)command的取值由/usr/include/linux/sockios.h所規(guī)定。這些command的由于功能的不同,可分為以下幾個小類:
• 改變路由表 (例如 SIOCADDRT, SIOCDELRT), 
• 讀/更新 ARP/RARP 緩存(如:SIOCDARP, SIOCSRARP), 
• 一般的與網(wǎng)絡(luò)接口有關(guān)的(例如 SIOCGIFNAME, SIOCSIFADDR 等等) 
在Gooodies 目錄下有很多樣例程序展示了如何使用ioctl。當(dāng)你看這些程序時,注意參數(shù)argstruct是與參數(shù)command相關(guān)的。例如,與路由表相關(guān)的 ioctl使用rtentry這種結(jié)構(gòu),rtentry定義在/usr/include/linux/route.h(參見例子 adddefault.c)。與ARP有關(guān)的ioctl調(diào)用使用arpreq結(jié)構(gòu),arpreq定義在 /usr/include/linux/if_arp.h(參見例子arpread.c)
與網(wǎng)絡(luò)接口有關(guān)的ioctl調(diào)用使用的command參數(shù)通??雌饋硐馭IOCxIFyyyy的形式,這里x要 么是S(設(shè)定set,寫write),要么是G(得到get,讀read)。在getifinfo.c程序中就使用了這種形式的command參數(shù)來讀 IP地址,硬件地址,廣播地址和得到與網(wǎng)絡(luò)接口有關(guān)的一些標(biāo)志(flag)。在這些ioctl調(diào)用中,第三個參數(shù)是ifreq結(jié)構(gòu),它在 /usr/include/linux/if.h中定義。在某些情況下, ioctrl調(diào)用可能會使用到在sockios.h之外的新的定義,例如,WaveLAN無線網(wǎng)絡(luò)卡會保存有關(guān)無線網(wǎng)絡(luò)信號強(qiáng)度的信息,這對用戶的程序可 能有用。但用戶怎么得到這種信息呢?我們的第一個本能是在sockios.h中定義新的ioctl命令,例如SIOCGIFWVLNSS(它的英文縮寫表 示W(wǎng)aveLAN的信號強(qiáng)度)。但不幸的是,這種命令不是對所有其他的網(wǎng)絡(luò)接口(例如:loopback環(huán)回接口)有意義,而且不應(yīng)當(dāng)允許對于 WAVLAN卡以外的網(wǎng)絡(luò)接口使用ioctl命令。那么,我們需要的是這樣一種機(jī)制:它能夠定義一種與網(wǎng)絡(luò)接口相關(guān)的ioctl命令。幸運(yùn)的是,在 Linux操作系統(tǒng)中已經(jīng)為實(shí)現(xiàn)這個目的內(nèi)建了一種掛鉤(hook)機(jī)制。當(dāng)你再次看sockios.h文件時,你將發(fā)現(xiàn)每一種設(shè)備已經(jīng)預(yù)先定義了 SIOCDEVPRIVATE的ioctl命令。而它的實(shí)現(xiàn)將留給開發(fā)相應(yīng)驅(qū)動程序的人去完成。
通常,一個用戶程序使用ioctl (sockid,SIOCDEVPRIVATE,(char*)&ifr)來調(diào)用與某種設(shè)備(指像WaveLAN那樣的特殊設(shè)備)相關(guān)的 ioctl命令,這里ifr是struct ifreq ifr形式的變量。用戶程序應(yīng)當(dāng)在ifr.ifr_name中填充與這個設(shè)備相關(guān)的名字,例如,假設(shè)WaveLAN使用的接口號為eth1。一般的,一個 用戶程序還需要與內(nèi)核互相交換ioctl的command參數(shù)和結(jié)果,這可以通過ifr.ifr_data這個變量來實(shí)現(xiàn),例如,想得到WaveLAN中 表示信號強(qiáng)度的信息時,可以通過返回這個變量來實(shí)現(xiàn)。Linux的源代碼已經(jīng)包括了兩種設(shè)備de4x5和ewrk3,它們定義并且實(shí)現(xiàn)了特定的ioctl 調(diào)用。這兩個設(shè)備的源代碼在de4x5.h,de4x5.c,ewrk3.h,ewrk3.c中(在 /usr/src/linux/drivers/net/目錄中)。這兩種設(shè)備都定義了它們特有的結(jié)構(gòu)(struct ewrk3_ioctl 和 struct de4x5_ioctl)來方便用戶程序和設(shè)備驅(qū)動之間交換信息。每次調(diào)用ioctl前,用戶程序應(yīng)當(dāng)在相應(yīng)的結(jié)構(gòu)變量中設(shè)定合適的初值,并且將 ifr.ifr_data指向該值。
在我們進(jìn)一步討論ewrk3和de4x5的代碼前,讓我們仔細(xì)看看ioctl調(diào)用是如何一步步地實(shí)現(xiàn)的。所有的和接口相關(guān)的ioctl請求 (SIOCxIFyyyy 和 SIOCDEVPRIVATE)將會調(diào)用dev_ioctl()(在/usr/src/linux/net/core/dev.c中)。但這只是一個包裝 器(wrapper),實(shí)際的動作將由dev_ifsioc()(也在dev.c中)來實(shí)現(xiàn)。差不多dev_ioctl()這個函數(shù)所做的所有工作只是檢 查這個調(diào)用是否已經(jīng)有了正當(dāng)?shù)臋?quán)限(例如,改變路由表需要有root的權(quán)限)。而dev_ifsioc()這個函數(shù)首先要做的一些事情包括得到與 ifr.ifr_name相匹配的設(shè)備的結(jié)構(gòu)(在/usr/include/linux/netdevice.h中定義)。但這是在實(shí)現(xiàn)特定的接口命令 (例如:SIOCGIFADDR)之后。這些特定的接口命令被放置到一個巨大的switch語句之中。其中SIOCDEVPRIVATE命令和其他的在 0x89F0到0x89FF之間的代碼將出現(xiàn)在switch語句中的一個分支——default語句中。內(nèi)核會檢查表示設(shè)備的結(jié)構(gòu)變量中,是否已經(jīng)定義了 一個與設(shè)備相關(guān)的ioctl句柄(handler)。這里的句柄是一個函數(shù)指針,它在表示設(shè)備的結(jié)構(gòu)變量中do_ioctl部分。如果已經(jīng)設(shè)置了這個句 柄,那么內(nèi)核將會執(zhí)行它。
所以,如果要實(shí)現(xiàn)一個與設(shè)備相關(guān)的ioctl命令,所要做的只是編寫一個與這個設(shè)備相關(guān)的ioctl句柄,并且將表示這 個設(shè)備的結(jié)構(gòu)變量中do_ioctl部分指向這個句柄。對于ewrk3這個設(shè)備,它的句柄是ewrk3_ioctl()(在ewrk3.c里面)并且相應(yīng) 的表示該設(shè)備的結(jié)構(gòu)變量由ewrk3_init()來初始化。在ewrk3_ioctl()的代碼中清晰的指出ifr.ifr_data是用作設(shè)備驅(qū)動程 序和用戶程序之間交換信息的。注意,這部分的內(nèi)存可以雙向的交流信息。例如,在ewrk3的驅(qū)動程序代碼中,if.ifr_data的頭兩個字節(jié)是用來表 示特殊的動作(例如,EWRK3_SET_PROM,EWRK3_CLR_PROM),而這個動作是符合使用者(驅(qū)動程序?qū)崿F(xiàn)了多個與設(shè)備相關(guān)的、由 SIOCDEVPRIVATE調(diào)用的命令)的要求的。另外,ifr.ifr_data中第5個字節(jié)指向的緩沖區(qū)(buffer)被用來交換其他的信息 (如:當(dāng)使用EWRK3_SET_HWADDR和EWRK3_GET_HWADDR時為硬件地址) 
在你深入ewrk3_ioctl()時,請注意一般情況下一個用戶進(jìn)程不能直接訪問內(nèi)核所在的內(nèi)存。為此,驅(qū)動開發(fā)者可以使用兩個特殊的函數(shù) memcpy_tofs()和memcpy_fromfs()。內(nèi)核函數(shù)memcpy_tofs(arg1, arg2, arg3) 從地址arg2(用戶空間)向地址arg1(內(nèi)核空間)拷貝arg3個字節(jié)。類似的,memcpy_fromfs(arg1,arg2,arg3)從地址 arg2(用戶空間)向地址arg1(內(nèi)核空間)拷貝arg3個字節(jié)。在這些調(diào)用之前,verify_area()將會檢查這個進(jìn)程是否擁有合適的訪問權(quán) 限。另外,注意使用printk()函數(shù)可以輸出debug信息。這個函數(shù)與printf()函數(shù)類似,但不能處理浮點(diǎn)類型的數(shù)。內(nèi)核代碼不能夠使用 printf()函數(shù)。printk()函數(shù)產(chǎn)生的結(jié)果將記錄在/usr/adm/messages里。如果想知道更多的關(guān)于這些函數(shù)的或者與它們相關(guān)的 信息,可以參考《Linux Kernel Hacker’s Guide》(在Linux文檔網(wǎng)站的首頁) 這本書中Supporting Functions部分。
 
使用ioctl與內(nèi)核交換數(shù)據(jù)
1. 前言 
使用ioctl系統(tǒng)調(diào)用是用戶空間向內(nèi)核交換數(shù)據(jù)的常用方法之一,從ioctl這個名稱上看,本意是針對I/O設(shè)備進(jìn)行的控制操作,但實(shí)際并不限制是真正的I/O設(shè)備,可以是任何一個內(nèi)核設(shè)備即可。
2. 基本過程
在內(nèi)核空間中ioctl是很多內(nèi)核操作結(jié)構(gòu)的一個成員函數(shù),如文件操作結(jié)構(gòu)struct file_operations(include/linux/fs.h)、協(xié)議操作結(jié)構(gòu)struct proto_ops(include/linux/net.h)等、tty操作結(jié)構(gòu)struct tty_driver(include/linux/tty_driver.h)等,而這些操作結(jié)構(gòu)分別對應(yīng)各種內(nèi)核設(shè)備,只要在用戶空間打開這些設(shè)備, 如I/O設(shè)備可用open(2)打開,網(wǎng)絡(luò)協(xié)議可用socket(2)打開等,獲取一個文件描述符后,就可以在這個描述符上調(diào)用ioctl(2)來向內(nèi)核 交換數(shù)據(jù)。
3. ioctl(2)
ioctl(2)函數(shù)的基本使用格式為:int ioctl(int fd, int cmd, void *data)
第一個參數(shù)是文件描述符;cmd是操作命令,一般分為GET、SET以及其他類型命令,GET是用戶空間進(jìn)程從內(nèi)核讀數(shù)據(jù),SET是用戶空間進(jìn)程向內(nèi)核寫數(shù)據(jù),cmd雖然是一個整數(shù),但是有一定的參數(shù)格式的,下面再詳細(xì)說明;第三個參數(shù)是數(shù)據(jù)起始位置指針,
cmd命令參數(shù)是個32位整數(shù),分為四部分:dir(2b)  size(14b)  type(8b) nr(8b)
詳細(xì)定義cmd要包括這4個部分時可使用宏_IOC(dir,type,nr,size)來定義,而最簡單情況下使用_IO(type, nr)來定義就可以了,這些宏都在include/asm/ioctl.h中定義
本文cmd定義為:
#define NEWCHAR_IOC_MAGIC   'M'
#define NEWCHAR_SET    _IO(NEWCHAR_IOC_MAGIC, 0)
#define NEWCHAR_GET    _IO(NEWCHAR_IOC_MAGIC, 1)
#define NEWCHAR_IOC_MAXNR   1
要定義自己的ioctl操作,可以有兩個方式,一種是在現(xiàn)有的內(nèi)核代碼中直接添加相關(guān)代碼進(jìn)行支持,比如想通過socket描述符進(jìn)行 ioctl操作,可在net/ipv4/af_inet.c中的inet_ioctl()函數(shù)中添加自己定義的命令和相關(guān)的處理函數(shù),重新編譯內(nèi)核即可, 不過這種方法一般不推薦;第二種方法是定義自己的內(nèi)核設(shè)備,通過設(shè)備的ioctl()來操作,可以編成模塊,這樣不影響原有的內(nèi)核,這是最通常的做法。
4. 內(nèi)核設(shè)備
為進(jìn)行ioctl操作最通常是使用字符設(shè)備來進(jìn)行,當(dāng)然定義其他類型的設(shè)備也可以。在用戶空間,可使用mknod命令建立一個字符類型設(shè)備文件,假設(shè)該設(shè)備的主設(shè)備號為123,次設(shè)備號為0:
mknode /dev/newchar c 123 0
如果是編程的話,可以用mknode(2)函數(shù)來建立設(shè)備文件。
建立設(shè)備文件后再將該設(shè)備的內(nèi)核模塊文件插入內(nèi)核,就可以使用open(2)打開/dev/newchar文件,然后調(diào)用ioctl(2)來傳遞數(shù)據(jù),最后用close(2)關(guān)閉設(shè)備。而如果內(nèi)核中還沒有插入該設(shè)備的模塊,open(2)時就會失敗。
由于內(nèi)核內(nèi)存空間和用戶內(nèi)存空間不同,要將內(nèi)核數(shù)據(jù)拷貝到用戶空間,要使用專用拷貝函數(shù)copy_to_user();要將用戶空間數(shù)據(jù)拷貝到內(nèi)核,要使用copy_from_user()。
要最簡單實(shí)現(xiàn)以上功能,內(nèi)核模塊只需要實(shí)現(xiàn)設(shè)備的open, ioctl和release三個函數(shù)即可,下面介紹程序片斷:
static int newchar_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
static int newchar_open(struct inode *inode, struct file *filep);
static int newchar_release(struct inode *inode, struct file *filep);
// 定義文件操作結(jié)構(gòu),結(jié)構(gòu)中其他元素為空
struct file_operations newchar_fops = 
{
 owner:  THIS_MODULE,
 ioctl:  newchar_ioctl,
 open:  newchar_open,
 release: newchar_release,
};
// 定義要傳輸?shù)臄?shù)據(jù)塊結(jié)構(gòu)
struct newchar{
 int a;
 int b;
};
#define MAJOR_DEV_NUM 123
#define DEVICE_NAME "newchar"
打開設(shè)備,非常簡單,就是增加模塊計數(shù)器,防止在打開設(shè)備的情況下刪除模塊,當(dāng)然想搞得復(fù)雜的話可進(jìn)行各種限制檢查,如只允許指定的用戶打開等:
static int newchar_open(struct inode *inode, struct file *filep)
{
 MOD_INC_USE_COUNT;
 return 0;
} 
關(guān)閉設(shè)備,也很簡單,減模塊計數(shù)器:
static int newchar_release(struct inode *inode, struct file *filep)
{
 MOD_DEC_USE_COUNT;
 return 0;
} 
進(jìn)行ioctl調(diào)用的基本處理函數(shù)
static int newchar_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
{
 int  ret;
// 首先檢查cmd是否合法
 if (_IOC_TYPE(cmd) != NEWCHAR_IOC_MAGIC) return -EINVAL;
 if (_IOC_NR(cmd) > NEWCHAR_IOC_MAXNR) return -EINVAL;
// 錯誤情況下的缺省返回值
 ret = EINVAL;
 switch(cmd)
 {
 case KNEWCHAR_SET:
// 設(shè)置操作,將數(shù)據(jù)從用戶空間拷貝到內(nèi)核空間
  {
   struct  newchar  nc;
   if(copy_from_user(&nc, (const char*)arg, sizeof(nc)) != 0)
    return -EFAULT;
   ret = do_set_newchar(&nc);
  }
  break;
 case KNEWCHAR_GET:
// GET操作通常會在數(shù)據(jù)緩沖區(qū)中先傳遞部分初始值作為數(shù)據(jù)查找條件,獲取全部
// 數(shù)據(jù)后重新寫回緩沖區(qū)
// 當(dāng)然也可以根據(jù)具體情況什么也不傳入直接向內(nèi)核獲取數(shù)據(jù)
  {
   struct  newchar  nc;
   if(copy_from_user(&nc, (const char*)arg, sizeof(nc)) != 0)
    return -EFAULT;
   ret = do_get_newchar(&nc);
   if(ret == 0){
    if(copy_to_user((unsigned char *)arg, &nc, sizeof(nc))!=0)
     return -EFAULT;
   }
  }
  break;
 }
 return ret;
}
模塊初始化函數(shù),登記字符設(shè)備
static int __init _init(void)
{
 int  result;
// 登記該字符設(shè)備,這是2.4以前的基本方法,到2.6后有了些變化,
// 是使用MKDEV和cdev_init()來進(jìn)行,本文還是按老方法
 result = register_chrdev(MAJOR_DEV_NUM, DEVICE_NAME, &newchar_fops);
 if (result < 0) {
  printk(KERN_WARNING __FUNCTION__ ": failed register character device for /dev/newchar\n");
  return result;
 }
 return 0;
}
模塊退出函數(shù),登出字符設(shè)備
static void __exit _cleanup(void)
{
 int  result;
 result = unregister_chrdev(MAJOR_DEV_NUM, DEVICE_NAME);
 if (result < 0)
  printk(__FUNCTION__ ": failed unregister character device for /dev/newchar\n");
 return;
} 
module_init(_init);
module_exit(_cleanup);
5. 結(jié)論
用ioctl()在用戶空間和內(nèi)核空間傳遞數(shù)據(jù)是最常用方法之一,比較簡單方便,而且可以在同一個ioctl中對不同的命令傳送不同的數(shù)據(jù)結(jié)構(gòu),本文只是為描述方便而在不同命令中使用了相同的數(shù)據(jù)結(jié)構(gòu)。
轉(zhuǎn)載:http://yfydz. 
 
 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    日韩人妻少妇一区二区| 亚洲国产色婷婷久久精品| 亚洲欧美精品伊人久久| 在线日韩中文字幕一区| 欧美一级内射一色桃子| 国产内射在线激情一区| 欧美日韩欧美国产另类| 亚洲日本久久国产精品久久| 国产在线日韩精品欧美| 亚洲中文在线男人的天堂| 中文字幕高清免费日韩视频| 国产美女精品午夜福利视频| 91香蕉视频精品在线看| 亚洲国产成人精品福利| 蜜臀人妻一区二区三区| 精品一区二区三区免费看| 国产精品一区二区高潮| 国产传媒中文字幕东京热| 成人午夜在线视频观看| 亚洲精品福利视频你懂的| 人妻偷人精品一区二区三区不卡| 国产内射一级一片内射高清| 欧美性欧美一区二区三区| 日韩不卡一区二区三区色图| 国产激情一区二区三区不卡| 不卡视频免费一区二区三区| 超薄丝袜足一区二区三区| 高清免费在线不卡视频| 日本黄色美女日本黄色| 精品香蕉一区二区在线| 欧美日韩精品综合一区| 日韩精品一区二区一牛| 国产一级特黄在线观看| 黄色日韩欧美在线观看| 国产麻豆一区二区三区在| 99一级特黄色性生活片| 亚洲最新中文字幕一区| 成年人免费看国产视频| 人体偷拍一区二区三区| 亚洲精品小视频在线观看| 国产精品一区二区三区日韩av|