【摘要】 Linux系統(tǒng)上的/proc目錄是一種文件系統(tǒng),即proc文件系統(tǒng)。 與其它常見(jiàn)的文件系統(tǒng)不同的是,/proc是一種偽文件系統(tǒng)(也即虛擬文件系統(tǒng)),存儲(chǔ)的是當(dāng)前內(nèi)核運(yùn)行狀態(tài)的一系列特殊文件,用戶(hù)可以通過(guò)這些文件查看有關(guān)系統(tǒng)硬件及當(dāng)前正在運(yùn)行進(jìn)程的信息,甚至可以通過(guò)更改其中某些文件來(lái)改變內(nèi)核的運(yùn)行狀態(tài)。
1. 前言
Linux系統(tǒng)上的/proc目錄是一種文件系統(tǒng),即proc文件系統(tǒng)。
與其它常見(jiàn)的文件系統(tǒng)不同的是,/proc是一種偽文件系統(tǒng)(也即虛擬文件系統(tǒng)),存儲(chǔ)的是當(dāng)前內(nèi)核運(yùn)行狀態(tài)的一系列特殊文件,用戶(hù)可以通過(guò)這些文件查看有關(guān)系統(tǒng)硬件及當(dāng)前正在運(yùn)行進(jìn)程的信息,甚至可以通過(guò)更改其中某些文件來(lái)改變內(nèi)核的運(yùn)行狀態(tài)。
當(dāng)前的實(shí)驗(yàn)平臺(tái)是嵌入式Linux開(kāi)發(fā)板,根文件系統(tǒng)掛載成功后,進(jìn)入命令就能看到proc
目錄,這個(gè)目錄里正常情況下已經(jīng)生成了很多文件。通過(guò)cat
命令讀取這些文件,可以得到很多內(nèi)核的信息。
比如:查看中斷有哪些注冊(cè)了,中斷從上電到現(xiàn)在響應(yīng)了多少次,雜項(xiàng)設(shè)備注冊(cè)了哪些,幀緩沖節(jié)點(diǎn)有哪些,RTC時(shí)間查看,等等。
下面是proc目錄下文件的功能的詳細(xì)介紹(資源來(lái)源與網(wǎng)絡(luò)):
2.1、/proc/apm
高級(jí)電源管理(APM)版本信息及電池相關(guān)狀態(tài)信息,通常由apm命令使用;2.2、/proc/buddyinfo
用于診斷內(nèi)存碎片問(wèn)題的相關(guān)信息文件;2.3、/proc/cmdline
在啟動(dòng)時(shí)傳遞至內(nèi)核的相關(guān)參數(shù)信息,這些信息通常由lilo或grub等啟動(dòng)管理工具進(jìn)行傳遞;2.4、/proc/cpuinfo
處理器的相關(guān)信息的文件;2.5、/proc/crypto
系統(tǒng)上已安裝的內(nèi)核使用的密碼算法及每個(gè)算法的詳細(xì)信息列表;2.6、/proc/devices
系統(tǒng)已經(jīng)加載的所有塊設(shè)備和字符設(shè)備的信息,包含主設(shè)備號(hào)和設(shè)備組(與主設(shè)備號(hào)對(duì)應(yīng)的設(shè)備類(lèi)型)名;2.7、/proc/diskstats
每塊磁盤(pán)設(shè)備的磁盤(pán)I/O統(tǒng)計(jì)信息列表;(內(nèi)核2.5.69以后的版本支持此功能)2.8、/proc/dma
每個(gè)正在使用且注冊(cè)的ISA DMA通道的信息列表;2.9、/proc/execdomains
內(nèi)核當(dāng)前支持的執(zhí)行域(每種操作系統(tǒng)獨(dú)特“個(gè)性”)信息列表;2.10、/proc/fb
幀緩沖設(shè)備列表文件,包含幀緩沖設(shè)備的設(shè)備號(hào)和相關(guān)驅(qū)動(dòng)信息;2.11、/proc/filesystems
當(dāng)前被內(nèi)核支持的文件系統(tǒng)類(lèi)型列表文件,被標(biāo)示為nodev的文件系統(tǒng)表示不需要塊設(shè)備的支持;通常mount一個(gè)設(shè)備時(shí),如果沒(méi)有指定文件系統(tǒng)類(lèi)型將通過(guò)此文件來(lái)決定其所需文件系統(tǒng)的類(lèi)型;2.12、/proc/interrupts
X86或X86_64體系架構(gòu)系統(tǒng)上每個(gè)IRQ相關(guān)的中斷號(hào)列表;多路處理器平臺(tái)上每個(gè)CPU對(duì)于每個(gè)I/O設(shè)備均有自己的中斷號(hào);2.13、/proc/iomem
每個(gè)物理設(shè)備上的記憶體(RAM或者ROM)在系統(tǒng)內(nèi)存中的映射信息;2.14、/proc/ioports
當(dāng)前正在使用且已經(jīng)注冊(cè)過(guò)的與物理設(shè)備進(jìn)行通訊的輸入-輸出端口范圍信息列表;如下面所示,第一列表示注冊(cè)的I/O端口范圍,其后表示相關(guān)的設(shè)備;2.15、/proc/kallsyms
模塊管理工具用來(lái)動(dòng)態(tài)鏈接或綁定可裝載模塊的符號(hào)定義,由內(nèi)核輸出;(內(nèi)核2.5.71以后的版本支持此功能);通常這個(gè)文件中的信息量相當(dāng)大;2.16、/proc/kcore
系統(tǒng)使用的物理內(nèi)存,以ELF核心文件(core file)格式存儲(chǔ),其文件大小為已使用的物理內(nèi)存(RAM)加上4KB;這個(gè)文件用來(lái)檢查內(nèi)核數(shù)據(jù)結(jié)構(gòu)的當(dāng)前狀態(tài),因此,通常由GBD通常調(diào)試工具使用,但不能使用文件查看命令打開(kāi)此文件;2.17、/proc/kmsg
此文件用來(lái)保存由內(nèi)核輸出的信息,通常由/sbin/klogd或/bin/dmsg等程序使用,不要試圖使用查看命令打開(kāi)此文件;2.18、/proc/loadavg
保存關(guān)于CPU和磁盤(pán)I/O的負(fù)載平均值,其前三列分別表示每1秒鐘、每5秒鐘及每15秒的負(fù)載平均值,類(lèi)似于uptime命令輸出的相關(guān)信息;第四列是由斜線(xiàn)隔開(kāi)的兩個(gè)數(shù)值,前者表示當(dāng)前正由內(nèi)核調(diào)度的實(shí)體(進(jìn)程和線(xiàn)程)的數(shù)目,后者表示系統(tǒng)當(dāng)前存活的內(nèi)核調(diào)度實(shí)體的數(shù)目;第五列表示此文件被查看前最近一個(gè)由內(nèi)核創(chuàng)建的進(jìn)程的PID;2.19、/proc/locks
保存當(dāng)前由內(nèi)核鎖定的文件的相關(guān)信息,包含內(nèi)核內(nèi)部的調(diào)試數(shù)據(jù);每個(gè)鎖定占據(jù)一行,且具有一個(gè)惟一的編號(hào);如下輸出信息中每行的第二列表示當(dāng)前鎖定使用的鎖定類(lèi)別,POSIX表示目前較新類(lèi)型的文件鎖,由lockf系統(tǒng)調(diào)用產(chǎn)生,F(xiàn)LOCK是傳統(tǒng)的UNIX文件鎖,由flock系統(tǒng)調(diào)用產(chǎn)生;第三列也通常由兩種類(lèi)型,ADVISORY表示不允許其他用戶(hù)鎖定此文件,但允許讀取,MANDATORY表示此文件鎖定期間不允許其他用戶(hù)任何形式的訪(fǎng)問(wèn);2.20、/proc/mdstat
保存RAID相關(guān)的多塊磁盤(pán)的當(dāng)前狀態(tài)信息,在沒(méi)有使用RAID機(jī)器上,其顯示為如下?tīng)顟B(tài):2.21、/proc/meminfo
系統(tǒng)中關(guān)于當(dāng)前內(nèi)存的利用狀況等的信息,常由free命令使用;可以使用文件查看命令直接讀取此文件,其內(nèi)容顯示為兩列,前者為統(tǒng)計(jì)屬性,后者為對(duì)應(yīng)的值;2.22、/proc/mounts
在內(nèi)核2.4.29版本以前,此文件的內(nèi)容為系統(tǒng)當(dāng)前掛載的所有文件系統(tǒng),在2.4.19以后的內(nèi)核中引進(jìn)了每個(gè)進(jìn)程使用獨(dú)立掛載名稱(chēng)空間的方式,此文件則隨之變成了指向/proc/self/mounts(每個(gè)進(jìn)程自身掛載名稱(chēng)空間中的所有掛載點(diǎn)列表)文件的符號(hào)鏈接;/proc/self是一個(gè)獨(dú)特的目錄,后文中會(huì)對(duì)此目錄進(jìn)行介紹;2.23、/proc/modules
當(dāng)前裝入內(nèi)核的所有模塊名稱(chēng)列表,可以由lsmod命令使用,也可以直接查看;如下所示,其中第一列表示模塊名,第二列表示此模塊占用內(nèi)存空間大小,第三列表示此模塊有多少實(shí)例被裝入,第四列表示此模塊依賴(lài)于其它哪些模塊,第五列表示此模塊的裝載狀態(tài)(Live:已經(jīng)裝入;Loading:正在裝入;Unloading:正在卸載),第六列表示此模塊在內(nèi)核內(nèi)存(kernel memory)中的偏移量;2.24、/proc/partitions
塊設(shè)備每個(gè)分區(qū)的主設(shè)備號(hào)(major)和次設(shè)備號(hào)(minor)等信息,同時(shí)包括每個(gè)分區(qū)所包含的塊(block)數(shù)目(如下面輸出中第三列所示);2.25、/proc/pci
內(nèi)核初始化時(shí)發(fā)現(xiàn)的所有PCI設(shè)備及其配置信息列表,其配置信息多為某PCI設(shè)備相關(guān)IRQ信息,可讀性不高,可以用“/sbin/lspci –vb”命令獲得較易理解的相關(guān)信息;在2.6內(nèi)核以后,此文件已為/proc/bus/pci目錄及其下的文件代替;2.26、/proc/slabinfo
在內(nèi)核中頻繁使用的對(duì)象(如inode、dentry等)都有自己的cache,即slab pool,而/proc/slabinfo文件列出了這些對(duì)象相關(guān)slap的信息;詳情可以參見(jiàn)內(nèi)核文檔中slapinfo的手冊(cè)頁(yè);2.27、/proc/stat
實(shí)時(shí)追蹤自系統(tǒng)上次啟動(dòng)以來(lái)的多種統(tǒng)計(jì)信息;如下所示,其中,
“cpu”行后的八個(gè)值分別表示以1/100(jiffies)秒為單位的統(tǒng)計(jì)值(包括系統(tǒng)運(yùn)行于用戶(hù)模式、低優(yōu)先級(jí)用戶(hù)模式,運(yùn)系統(tǒng)模式、空閑模式、I/O等待模式的時(shí)間等);
“intr”行給出中斷的信息,第一個(gè)為自系統(tǒng)啟動(dòng)以來(lái),發(fā)生的所有的中斷的次數(shù);然后每個(gè)數(shù)對(duì)應(yīng)一個(gè)特定的中斷自系統(tǒng)啟動(dòng)以來(lái)所發(fā)生的次數(shù);
“ctxt”給出了自系統(tǒng)啟動(dòng)以來(lái)CPU發(fā)生的上下文交換的次數(shù)。
“btime”給出了從系統(tǒng)啟動(dòng)到現(xiàn)在為止的時(shí)間,單位為秒;
“processes (total_forks) 自系統(tǒng)啟動(dòng)以來(lái)所創(chuàng)建的任務(wù)的個(gè)數(shù)目;
“procs_running”:當(dāng)前運(yùn)行隊(duì)列的任務(wù)的數(shù)目;
“procs_blocked”:當(dāng)前被阻塞的任務(wù)的數(shù)目;2.28、/proc/swaps
當(dāng)前系統(tǒng)上的交換分區(qū)及其空間利用信息,如果有多個(gè)交換分區(qū)的話(huà),則會(huì)每個(gè)交換分區(qū)的信息分別存儲(chǔ)于/proc/swap目錄中的單獨(dú)文件中,而其優(yōu)先級(jí)數(shù)字越低,被使用到的可能性越大;下面是作者系統(tǒng)中只有一個(gè)交換分區(qū)時(shí)的輸出信息;2.29、/proc/uptime
系統(tǒng)上次啟動(dòng)以來(lái)的運(yùn)行時(shí)間,如下所示,其第一個(gè)數(shù)字表示系統(tǒng)運(yùn)行時(shí)間,第二個(gè)數(shù)字表示系統(tǒng)空閑時(shí)間,單位是秒;2.30、/proc/version
當(dāng)前系統(tǒng)運(yùn)行的內(nèi)核版本號(hào),在作者的RHEL5.3上還會(huì)顯示系統(tǒng)安裝的gcc版本,如下所示;2.31、/proc/vmstat
當(dāng)前系統(tǒng)虛擬內(nèi)存的多種統(tǒng)計(jì)數(shù)據(jù),信息量可能會(huì)比較大,這因系統(tǒng)而有所不同,可讀性較好;下面為作者機(jī)器上輸出信息的一個(gè)片段;(2.6以后的內(nèi)核支持此文件)2.32、/proc/zoneinfo
內(nèi)存區(qū)域(zone)的詳細(xì)信息列表,信息量較大
2. 獲取CPU使用率
下面這份代碼是利用/proc/stat
文件獲取當(dāng)前CPU的占用率詳細(xì)信息,通過(guò)C語(yǔ)言代碼讀取數(shù)據(jù)后,進(jìn)行分析,處理。
#include
#include
#include
typedef struct cpu_occupy_ //定義一個(gè)cpu occupy的結(jié)構(gòu)體
{
char name[20]; //定義一個(gè)char類(lèi)型的數(shù)組名name有20個(gè)元素
unsigned int user; //定義一個(gè)無(wú)符號(hào)的int類(lèi)型的user
unsigned int nice; //定義一個(gè)無(wú)符號(hào)的int類(lèi)型的nice
unsigned int system; //定義一個(gè)無(wú)符號(hào)的int類(lèi)型的system
unsigned int idle; //定義一個(gè)無(wú)符號(hào)的int類(lèi)型的idle
unsigned int iowait;
unsigned int irq;
unsigned int softirq;
}cpu_occupy_t;
double cal_cpuoccupy (cpu_occupy_t *o, cpu_occupy_t *n)
{
double od, nd;
double id, sd;
double cpu_use ;
od = (double) (o->user + o->nice + o->system +o->idle+o->softirq+o->iowait+o->irq);//第一次(用戶(hù)+優(yōu)先級(jí)+系統(tǒng)+空閑)的時(shí)間再賦給od
nd = (double) (n->user + n->nice + n->system +n->idle+n->softirq+n->iowait+n->irq);//第二次(用戶(hù)+優(yōu)先級(jí)+系統(tǒng)+空閑)的時(shí)間再賦給od
id = (double) (n->idle); //用戶(hù)第一次和第二次的時(shí)間之差再賦給id
sd = (double) (o->idle) ; //系統(tǒng)第一次和第二次的時(shí)間之差再賦給sd
if((nd-od) != 0)
cpu_use =100.0 - ((id-sd))/(nd-od)*100.00; //((用戶(hù)+系統(tǒng))乖100)除(第一次和第二次的時(shí)間差)再賦給g_cpu_used
else
cpu_use = 0;
return cpu_use;
}
void get_cpuoccupy (cpu_occupy_t *cpust)
{
FILE *fd;
int n;
char buff[256];
cpu_occupy_t *cpu_occupy;
cpu_occupy=cpust;
fd = fopen ("/proc/stat", "r");
if(fd == NULL)
{
perror("fopen:");
exit (0);
}
fgets (buff, sizeof(buff), fd);
sscanf (buff, "%s %u %u %u %u %u %u %u", cpu_occupy->name, &cpu_occupy->user, &cpu_occupy->nice,&cpu_occupy->system, &cpu_occupy->idle ,&cpu_occupy->iowait,&cpu_occupy->irq,&cpu_occupy->softirq);
fclose(fd);
}
double get_sysCpuUsage()
{
cpu_occupy_t cpu_stat1;
cpu_occupy_t cpu_stat2;
double cpu;
get_cpuoccupy((cpu_occupy_t *)&cpu_stat1);
sleep(1);
//第二次獲取cpu使用情況
get_cpuoccupy((cpu_occupy_t *)&cpu_stat2);
//計(jì)算cpu使用率
cpu = cal_cpuoccupy ((cpu_occupy_t *)&cpu_stat1, (cpu_occupy_t *)&cpu_stat2);
return cpu;
}
int main(int argc,char **argv)
{
while(1)
{
printf("CPU占用率:%f\n",get_sysCpuUsage());
}
return 0;
}
3. proc驅(qū)動(dòng)相關(guān)接口
Proc文件接口,主要用于驅(qū)動(dòng)代碼調(diào)試,獲取內(nèi)核信息,可以直接使用cat命令訪(fǎng)問(wèn)proc目錄下的對(duì)應(yīng)文件接口即可。
需要使用的頭文件:
#include
#include
下面介紹內(nèi)核里proc接口實(shí)現(xiàn)的相關(guān)函數(shù)接口:
1. 在proc目錄下創(chuàng)建子目錄函數(shù)
static inline struct proc_dir_entry *proc_mkdir(const char *name,struct proc_dir_entry *parent)
示例: //注意只能創(chuàng)建單層目錄
//在proc目錄下創(chuàng)建aaa文件夾
proc_mkdir("aaa",NULL);
2. 在proc目錄下創(chuàng)建文件
static inline struct proc_dir_entry *proc_create(const char *name, //文件名稱(chēng)
umode_t mode, //模式,默認(rèn)為0
struct proc_dir_entry *parent, //父目錄結(jié)構(gòu)
const struct file_operations *proc_fops) //文件集合
示例:
//在proc目錄下創(chuàng)建一個(gè)文件
proc_create("aaa/tiny4412_proc_test", 0, NULL, &fops_proc);
3. 刪除proc目錄下之前創(chuàng)建的文件或者目錄
void remove_proc_entry(const char *name, //文件的路徑
struct proc_dir_entry *parent //父目錄結(jié)構(gòu)
)
示例:
remove_proc_entry("aaa/tiny4412_proc_test", NULL);
注意: 如果是刪除目錄,需要先把目錄下的文件刪除掉,每次刪除必須保證目錄是空的。
4. 編寫(xiě)proc接口測(cè)試驅(qū)動(dòng)
4.1 案例1
下面驅(qū)動(dòng)代碼注冊(cè)之后,會(huì)在proc目錄下創(chuàng)建一個(gè)tiny4412_proc
文件,通過(guò)cat讀取這個(gè)文件,可以打印驅(qū)動(dòng)代碼里設(shè)置好的信息。驅(qū)動(dòng)卸載時(shí)會(huì)刪除這個(gè)tiny4412_proc
文件。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static int tiny4412_open(struct inode *inode, struct file *file)
{
printk("tiny4412_open ok\n");
return 0;
}
static ssize_t tiny4412_read(struct file *file, char __user *buf, size_t cnt, loff_t *loff)
{
copy_to_user(buf,"123456",6);
printk("tiny4412_read調(diào)用成功.\n");
return 0;
}
static int tiny4412_release(struct inode *inode, struct file *file)
{
return 0;
}
static struct file_operations tiny4412_fops=
{
.open=tiny4412_open,
.read=tiny4412_read,
.release=tiny4412_release,
};
static int __init tiny4412_init(void)
{
proc_mkdir("wbyq",0);
/*創(chuàng)建內(nèi)核接口: proc 存放內(nèi)核信息*/
proc_create("wbyq/tiny4412_proc",0, NULL, &tiny4412_fops);
printk("驅(qū)動(dòng)安裝成功.\n");
return 0;
}
static void __exit tiny4412_exit(void)
{
remove_proc_entry("wbyq/tiny4412_proc", NULL);
remove_proc_entry("wbyq", NULL);
printk("驅(qū)動(dòng)卸載成功.\n");
}
/*驅(qū)動(dòng)的入口:insmod xxx.ko*/
module_init(tiny4412_init);
/*驅(qū)動(dòng)的出口: rmmod xxx.ko*/
module_exit(tiny4412_exit);
/*模塊的許可證*/
MODULE_LICENSE("GPL");
/*模塊的作者*/
MODULE_AUTHOR("wbyq");
4.2 案例2
下面這份代碼是在字符設(shè)備框架代碼里增加了proc接口,驅(qū)動(dòng)安裝之后,會(huì)在proc目錄下創(chuàng)建tiny4412_proc
文件,通過(guò)cat命令讀取tiny4412_proc
文件,可以打印出當(dāng)前主設(shè)備號(hào)下所有的子設(shè)備信息。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static struct class *tiny4412_beep_class;
static unsigned int major=0; //主設(shè)備號(hào)
static LIST_HEAD(tiny4412_beep_list); //鏈表頭
static DEFINE_MUTEX(tiny4412_beep_mtx); //互斥鎖
#define DYNAMIC_MINORS 64 /* like dynamic majors */
static DECLARE_BITMAP(beep_minors, DYNAMIC_MINORS);
struct tiny4412_beep_device
{
int minor; /*次設(shè)備號(hào)*/
const char *name; /*設(shè)備節(jié)點(diǎn)的名稱(chēng)*/
const struct file_operations *fops; /*文件操作集合*/
struct list_head list; //鏈表
};
int tiny4412_beep_register(struct tiny4412_beep_device *beep_dev)
{
struct tiny4412_beep_device *c;
dev_t dev;
INIT_LIST_HEAD(&beep_dev->list);
mutex_lock(&tiny4412_beep_mtx);
//查找傳入的次設(shè)備號(hào)是否沖突
list_for_each_entry(c, &tiny4412_beep_list, list)
{
if(c->minor == beep_dev->minor)
{
mutex_unlock(&tiny4412_beep_mtx);
return -EBUSY;
}
}
//自動(dòng)分配
if(beep_dev->minor == MISC_DYNAMIC_MINOR)
{
int i = find_first_zero_bit(beep_minors,DYNAMIC_MINORS);
if (i >= DYNAMIC_MINORS)
{
mutex_unlock(&tiny4412_beep_mtx);
return -EBUSY;
}
beep_dev->minor = DYNAMIC_MINORS - i - 1;
set_bit(i,beep_minors);
}
//合成設(shè)備號(hào)
dev = MKDEV(major, beep_dev->minor);
//創(chuàng)建設(shè)備節(jié)點(diǎn)
device_create(tiny4412_beep_class,NULL,dev,NULL,"%s", beep_dev->name);
list_add(&beep_dev->list,&tiny4412_beep_list);
//解鎖
mutex_unlock(&tiny4412_beep_mtx);
return 0;
}
int tiny4412_beep_deregister(struct tiny4412_beep_device *beep_dev)
{
int i = DYNAMIC_MINORS - beep_dev->minor - 1;
mutex_lock(&tiny4412_beep_mtx);
list_del(&beep_dev->list);
//將dev目錄下的文件刪除掉
device_destroy(tiny4412_beep_class, MKDEV(major, beep_dev->minor));
if (i < DYNAMIC_MINORS && i >= 0)
clear_bit(i, beep_minors);
mutex_unlock(&tiny4412_beep_mtx);
return 0;
}
EXPORT_SYMBOL_GPL(tiny4412_beep_register);
EXPORT_SYMBOL_GPL(tiny4412_beep_deregister);
//底層open函數(shù)
static int tiny4412_beep_open(struct inode * inode, struct file * file)
{
//得到次設(shè)備號(hào)
int minor = iminor(inode);
struct tiny4412_beep_device *c;
struct file_operations *new_fops,*old_fops;
mutex_lock(&tiny4412_beep_mtx);
//遍歷鏈表--找到鏈表里相同的次設(shè)備號(hào)
list_for_each_entry(c,&tiny4412_beep_list, list)
{
if (c->minor == minor)
{
new_fops = fops_get(c->fops); //得到47次設(shè)備號(hào)對(duì)應(yīng)的結(jié)構(gòu)體地址
break;
}
}
file->f_op = new_fops; //改變指向--文件操作集合的指向
if(file->f_op->open)
{
file->f_op->open(inode,file);
}
fops_put(old_fops);
mutex_unlock(&tiny4412_beep_mtx);
return 0;
}
static const struct file_operations tiny4412_beep_fops =
{
.owner = THIS_MODULE,
.open = tiny4412_beep_open,
};
static ssize_t tiny4412_read(struct file *file, char __user *buf, size_t cnt, loff_t *loff)
{
struct tiny4412_beep_device *c;
//遍歷鏈表--找到鏈表里相同的次設(shè)備號(hào)
list_for_each_entry(c,&tiny4412_beep_list, list)
{
printk("%d %s\n",c->minor,c->name);
}
return 0;
}
static struct file_operations tiny4412_fops=
{
.read=tiny4412_read,
};
static int __init tiny4412_beep_class_init(void)
{
/*1. 創(chuàng)建設(shè)備類(lèi)*/
tiny4412_beep_class=class_create(THIS_MODULE,"tiny4412_beep");
/*2. 注冊(cè)字符設(shè)備*/
major=register_chrdev(0,"tiny4412_beep",&tiny4412_beep_fops);
proc_mkdir("wbyq",0);
/*創(chuàng)建內(nèi)核接口: proc 存放內(nèi)核信息*/
proc_create("wbyq/tiny4412_proc",0, NULL, &tiny4412_fops);
return 0;
}
static void __exit tiny4412_beep_class_cleanup(void)
{
remove_proc_entry("wbyq/tiny4412_proc", NULL);
remove_proc_entry("wbyq", NULL);
//注銷(xiāo)設(shè)備類(lèi)
class_destroy(tiny4412_beep_class);
//注銷(xiāo)字符設(shè)備
unregister_chrdev(major,"tiny4412_beep");
}
module_init(tiny4412_beep_class_init);
module_exit(tiny4412_beep_class_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wbyq");
-
接口
+關(guān)注
關(guān)注
33文章
8694瀏覽量
151928 -
Linux
+關(guān)注
關(guān)注
87文章
11345瀏覽量
210408 -
Proc
+關(guān)注
關(guān)注
0文章
12瀏覽量
9023
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
迅為RK3568開(kāi)發(fā)板驅(qū)動(dòng)指南Linux中通用SPI設(shè)備驅(qū)動(dòng)
![迅為RK3568<b class='flag-5'>開(kāi)發(fā)</b>板<b class='flag-5'>驅(qū)動(dòng)</b>指南<b class='flag-5'>Linux</b>中通用SPI設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b>](https://file1.elecfans.com/web3/M00/06/FF/wKgZO2eRsTyAQNODAACATQzlR7A177.png)
北京迅為RK3568開(kāi)發(fā)板嵌入式學(xué)習(xí)之Linux驅(qū)動(dòng)全新更新-CAN+
![北京迅為RK3568<b class='flag-5'>開(kāi)發(fā)</b>板嵌入式學(xué)習(xí)之<b class='flag-5'>Linux</b><b class='flag-5'>驅(qū)動(dòng)</b>全新更新-CAN+](https://file1.elecfans.com/web2/M00/06/25/wKgaombYDFKAD0JxAADlDQo6OXo738.png)
嵌入式linux開(kāi)發(fā)的基本步驟有哪些?
嵌入式linux開(kāi)發(fā)板怎么操作
嵌入式linux開(kāi)發(fā)板芯片的工作原理
linux開(kāi)發(fā)板與樹(shù)莓派的區(qū)別
linux系統(tǒng)的設(shè)備驅(qū)動(dòng)一般分幾類(lèi)
linux驅(qū)動(dòng)程序如何加載進(jìn)內(nèi)核
linux驅(qū)動(dòng)程序的編譯方法是什么
Linux 驅(qū)動(dòng)開(kāi)發(fā)與應(yīng)用開(kāi)發(fā),你知道多少?
![<b class='flag-5'>Linux</b> <b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>與應(yīng)用<b class='flag-5'>開(kāi)發(fā)</b>,你知道多少?](https://file.elecfans.com/web2/M00/20/B3/pYYBAGGfNNmAK-PZAAJsGM5Cgk0227.jpg)
虹科技術(shù) 全新Linux環(huán)境PCAN驅(qū)動(dòng)程序發(fā)布!CAN/CAN FD通信體驗(yàn)全面升級(jí)!
![虹科技術(shù) 全新<b class='flag-5'>Linux</b>環(huán)境PCAN<b class='flag-5'>驅(qū)動(dòng)</b>程序發(fā)布!CAN/CAN FD通信體驗(yàn)全面升級(jí)!](https://file1.elecfans.com//web2/M00/05/73/wKgaombP0KOAN4sCAABI2TSngu8284.png)
Linux中的proc介紹
![<b class='flag-5'>Linux</b>中的<b class='flag-5'>proc</b><b class='flag-5'>介紹</b>](https://file1.elecfans.com/web2/M00/02/94/wKgZoma8g7OARd4_AAW33AFOb04808.png)
全新Linux環(huán)境PCAN驅(qū)動(dòng)程序發(fā)布!CAN/CAN FD通信體驗(yàn)全面升級(jí)!
ArmSoM系列板卡 嵌入式Linux驅(qū)動(dòng)開(kāi)發(fā)實(shí)戰(zhàn)指南 之 字符設(shè)備驅(qū)動(dòng)
![ArmSoM系列板卡 嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>實(shí)戰(zhàn)指南 之 字符設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b>](https://file1.elecfans.com//web2/M00/C7/A6/wKgZomYVR9GANLMOAAFxQgXISF0915.png)
評(píng)論