Linux驅(qū)動(dòng)程序之統(tǒng)計(jì)單詞個(gè)數(shù)

0. 需要的頭文件、宏及變量
  1 #include <linux/module.h>                                                                                                                                                                               
  2 #include <linux/init.h>
  3 #include <linux/kernel.h>
  4 #include <linux/fs.h>
  5 #include <linux/miscdevice.h>
  6 #include <linux/uaccess.h>
  7 
  8 // 定義一些宏和變量
  9 #define DEVICE_NAME "wordcount"  // 定義設(shè)備文件名
 10 static unsigned char mem[10000]; // 保存向設(shè)備文件寫(xiě)入的數(shù)據(jù)
 11 // static char read_flag = 'y';  // y:已從設(shè)備文件讀取數(shù)據(jù) n:未讀取數(shù)據(jù)
 12 static int word_count = 0;  // 單詞數(shù) 
 13 #define TRUE -1
 14 #define FALSE 0
1. 建立Linux驅(qū)動(dòng)骨架(裝載和卸載Linux驅(qū)動(dòng))

裝載

// 初始化Linux驅(qū)動(dòng)                                                                                                                                                       
 static int word_count_init(void)
 {
     int ret;
     // 建立設(shè)備文件
     ret = misc_register(&misc);
     // 輸出日志信息
     printk("word_count_init_success\n");
     return ret;
 }

卸載

 // 退出Linux驅(qū)動(dòng)
 static void word_count_exit(void)
 {
     // 移除設(shè)備文件
     misc_deregister(&misc);
     // 輸出日志信息
     printk("word_count_exit_success\n");
   }

注冊(cè)Linux驅(qū)動(dòng)加載和卸載函數(shù):

module_init(word_count_init);
module_exit(word_count_exit);
2.注冊(cè)和注銷設(shè)備文件

指定設(shè)備文件信息:

// 描述與設(shè)備文件觸發(fā)的事件對(duì)應(yīng)的回調(diào)函數(shù)指針                                                                                                                            
// owner:設(shè)備事件回調(diào)函數(shù)應(yīng)用于哪些驅(qū)動(dòng)模塊,THIS_MODULE表示應(yīng)用于當(dāng)前驅(qū)動(dòng)模塊                                                                                          
// 需要設(shè)置read和write成員變量,系統(tǒng)才能調(diào)用處理讀寫(xiě)設(shè)備文件動(dòng)作的函數(shù)                                                                                                   
static struct file_operations dev_fops =                                                                                                                                 
{ .owner = THIS_MODULE, .read = word_count_read, .write = word_count_write };                                                                                            
                                                                                                                                                                        
// 描述設(shè)備文件的信息                                                                                                                                                    
// minor: 次設(shè)備號(hào)  MISC_DYNAMIC_MINOR:動(dòng)態(tài)生成次設(shè)備號(hào) name: 設(shè)備文件名稱                                                                                              
// fops: file_operations結(jié)構(gòu)體變量指針                                                                                                                                   
static struct miscdevice misc =                                                                                                                                          
{ .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops };  

注冊(cè)和注銷動(dòng)作已于步驟1中通過(guò)misc_register和 misc_deregister函數(shù)完成。

3. 指定與驅(qū)動(dòng)相關(guān)的信息
// 驅(qū)動(dòng)相關(guān)信息
MODULE_AUTHOR("LAZIJI");
MODULE_DESCRIPTION("statistics of word count");
MODULE_ALIAS("word count module");
 MODULE_LICENSE("GPL");
4. 編寫(xiě)回調(diào)函數(shù)

讀取設(shè)備文件數(shù)據(jù)的函數(shù)

 // file:指向設(shè)備文件  buf:保存可讀取的數(shù)據(jù) count:可讀取的字節(jié)數(shù)  ppos:讀取數(shù)據(jù)的偏移量                                                                               
 static ssize_t word_count_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)                                                                          
 {                                                                                                                                                                        
     unsigned char temp[4];                                                                                                                                               
     // 將單詞數(shù)(int類型)分解成4個(gè)字節(jié)存儲(chǔ)在buf中                                                                                                                       
     temp[0] = word_count >> 24;                                                                                                                                          
     temp[1] = word_count >> 16;                                                                                                                                          
     temp[2] = word_count >> 8;                                                                                                                                           
     temp[3] = word_count;                                                                                                                                                
     copy_to_user(buf, (void*) temp, 4);                                                                                                                                  
     printk("read:word count:%d", (int) count);                                                                                                                                                                                                                                                                                                     
     return count;                                                                                                                                                                                                                                                                                                                              
 }

向設(shè)備文件寫(xiě)數(shù)據(jù)的函數(shù)

 // file:指向設(shè)備文件  buf:保存寫(xiě)入的數(shù)據(jù) count:寫(xiě)入數(shù)據(jù)的字節(jié)數(shù)  ppos:寫(xiě)入數(shù)據(jù)的偏移量                                                                               
 static ssize_t word_count_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)                                                                   
 {                                                                                                                                                                        
     ssize_t written = count;                                                                                                                                             
                                                                                                                                                                          
     copy_from_user(mem, buf, count);                                                                                                                                     
     mem[count] = '\0';                                                                                                                                                   
     // 統(tǒng)計(jì)單詞數(shù)                                                                                                                                                        
     word_count = get_word_count(mem);                                                                                                                                    
     printk("write:word count:%d", (int) word_count);                                                                                                                     
     return written; 
 }
5.編寫(xiě)業(yè)務(wù)邏輯

判斷字符是否為空格(包括空格符、制表符、回車符和換行符)

 static char is_spacewhite(char c)                                                                                                                                        
 {                                                                                                                                                                        
     if(c == ' ' || c == 9 || c == 13 || c == 10)                                                                                                                         
         return TRUE;                                                                                                                                                     
     else                                                                                                                                                                 
         return FALSE;                                                                                                                                                    
 }

統(tǒng)計(jì)單詞數(shù)

 static int get_word_count(const char *buf)                                                                                                                               
 {                                                                                                                                                                        
     int n = 1;                                                                                                                                                           
     int i = 0;                                                                                                                                                           
     char c = ' ';                                                                                                                                                        
                                                                                                                                                                          
 // 處理多個(gè)空格分隔的情況,0:正常情況,1:已遇到一個(gè)空格                                                                                             
     if(*buf == '\0')                                                                                                                                                     
         return 0;                                                                                                                                                        
     // 第1個(gè)字符是空格,從0開(kāi)始計(jì)數(shù)                                                                                                                                      
     if(is_spacewhite(*buf) == TRUE)                                                                                                                                      
         n--;                                                                                                                                                             
     // 掃描字符串中的每一個(gè)字符                                                                                                                                          
     for (; (c = *(buf + i)) != '\0'; i++)                                                                                                                                
        {                                                                                                                                                                    
         // 只由一個(gè)空格分割單詞的情況                                                                                                                                    
         if(flag == 1 && is_spacewhite(c) == FALSE)                                                                                                                       
         {                                                                                                                                                                
             flag = 0;                                                                                                                                                    
         }                                                                                                                                                                
         // 由多個(gè)空格分隔單詞的情況,忽略多余的空格                                                                                                                      
         else if(flag == 1 && is_spacewhite(c) == TRUE)                                                                                                                   
         {                                                                                                                                                                
             continue;                                                                                                                                                    
         }                                                                                                                                                                
         // 當(dāng)前字符為空格時(shí)單詞數(shù)加1                                                                                                                                     
         if(is_spacewhite(c) == TRUE)                                                                                                                                     
         {                                                                                                                                                                
             n++;                                                                                                                                                         
             flag = 1;                                                                                                                                                    
         }                                                                                                                                                                
     }                                                                                                                                                                    
     if(is_spacewhite(*(buf + i - 1)) == TRUE)                                                                                                                            
         n--;                                                                                                                                                             
     return n;
 }
6.編寫(xiě)Makefile文件
  1 obj-m := word_count1.o
  2 
  3 PWD := $(shell pwd)                                                                                                                                                                                     
  4 KernelDir :=/lib/modules/$(shell uname -r)/build/
  5    
  6 all:
  7     $(MAKE) -C $(KernelDir) M=$(PWD) modules
  8 
  9 all_install:
 10     $(MAKE) -C $(KernelDir) M=$(PWD) modules_install
 11 
 12 clean:
 13     rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.symvers *.order *.mod
 14 .PHOHY: modules modules_install clean
7.編譯Linux驅(qū)動(dòng)程序

編譯為模塊的步驟:將驅(qū)動(dòng)程序和Makefile文件放到同一目錄下,將命令行切換到該目錄下,輸入make完成編譯,產(chǎn)生.ko文件。

8.安裝和卸載Linux驅(qū)動(dòng)

分別輸入insmod + .ko文件和rmmod + .ko文件完成安裝和卸載

9. Linux驅(qū)動(dòng)測(cè)試

測(cè)試程序test.c

  1 #include <stdio.h>                                                                                                                                                                                      
  2 #include <fcntl.h>
  3 #include <unistd.h>
  4 #include <stdlib.h>
  5 #include <string.h>
  6 int main(int argc, char *argv[])
  7 {
  8     int testdev;   // 打開(kāi)設(shè)備文件(/dev/wordcount)的句柄
  9     unsigned char buf[4];  // 表示單詞數(shù)的4個(gè)字節(jié)
 10     // 打開(kāi)設(shè)備文件
 11     testdev = open("/dev/wordcount", O_RDWR);
 12     // 如果open函數(shù)返回-1,表示打開(kāi)設(shè)備文件失敗
 13     if (testdev == -1)
 14     {
 15         printf("Cann't open file \n");
 16         return 0;
 17     }
 18     // 如果test_word_count后面跟有命令行參數(shù),程序會(huì)將第1個(gè)參數(shù)值當(dāng)做待統(tǒng)計(jì)的字符串
 19     // 如果沒(méi)有命令行參數(shù),則只讀取設(shè)備文件中的值
 20     if (argc > 1)
 21     {
 22         // 向設(shè)備文件寫(xiě)入待統(tǒng)計(jì)的字符串
 23         write(testdev, argv[1], strlen(argv[1]));
 24         // 輸出待統(tǒng)計(jì)的字符串
 25         printf("string:%s\n", argv[1]);
 26     }
 27     // 讀取設(shè)備文件中的單詞數(shù)(4個(gè)字節(jié))
 28     read(testdev, buf, 4);
 29 
 30     int n = 0; // 單詞數(shù)
 31 
 32     // 將4個(gè)字節(jié)還原成int類型的值  
 33     n = ((int) buf[0]) << 24 |((int) buf[1]) << 16 | ((int) buf[2]) << 8 | ((int) buf[3]); 
 34     // 分別輸出從設(shè)備文件獲取的4個(gè)字節(jié)的值
 35     printf("word byte display:%d,%d,%d,%d\n", buf[0], buf[1], buf[2], buf[3]);
 36     // 輸出統(tǒng)計(jì)出的單詞數(shù)
 37     printf("word count:%d\n", n);  
 38     // 關(guān)閉設(shè)備文件
 39     close(testdev);
 40 
 41     return 0;
 42 }

編譯測(cè)試代碼:在終端輸入 gcc test.c -o test
執(zhí)行測(cè)試代碼:在終端輸入 ./test "la zi ji zhen de la"
終端顯示的結(jié)果:
string:la zi ji zhen de la
word byte display:0,0,0,6
word count:6

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容