核心必須懂 五 per CPU變數

2021-09-14 03:38:37 字數 3436 閱讀 1920

核心必須懂(一): 用系統呼叫列印hello, world!

核心必須懂(二): 檔案系統初探

核心必須懂(三): 重編ubuntu18.04lts核心4.15.0

核心必須懂(四): 撰寫核心驅動

之前核心必須懂(四): 撰寫核心驅動說到了基礎的驅動模組寫法. 這次目標就是計算進入驅動ioctl或者其他某個驅動函式的次數. 當然, 你可能會覺得, 這弄個全域性變數計數不就完了嗎? 但是這裡的要求是要並行進行訪問, 所以統計的是多核多執行緒的訪問次數. 是不是感覺沒有那麼簡單了? 你可能會回答, 上鎖, 那基本等於序列, 太low, 這裡展示真正的並行訪問與計數.

先來看下使用者態**:

#include #include #include #include #include #include #include #include using namespace std;

#define num_threads 20

// 檔案描述符

int fd = 0;

// 多執行緒呼叫函式

void *pthread_fx( void *args )

int main()

// 開啟多執行緒

pthread_t tids[num_threads];

for ( int i = 0; i < num_threads; ++i )

} // **執行緒資源

for ( int i = 0; i < num_threads; ++i )

// 關閉檔案

close( fd );

return 0;

}

這裡就是開20個執行緒呼叫驅動的ioctl函式. 沒什麼要說的.

是依據上一次的內容核心必須懂(四): 撰寫核心驅動擴充套件的, 變化基本在driverclosedriveriocontrol兩個函式中.

#include #include #include #include #include #define    major_num    231

#define device_name "hellodr"

define_per_cpu( long, gusage ) = 0;

int driveropen( struct inode *pslinode, struct file *pslfilestruct )

ssize_t driverwrite( struct file *pslfilestruct, const char __user *pbuffer, size_t ncount, loff_t *poffset )

int driverclose( struct inode *pslinode, struct file *pslfilestruct )

printk( kern_alert device_name " %ld\n", usagesum );

return(0);

}long driveriocontrol( struct file *pslfilestruct, unsigned int uicmd, unsigned long ularg )

struct file_operations hello_flops = ;

static int __init hello_init( void )

printk( kern_alert device_name " initialized.\n" );

return(0);

}static void __exit hello_exit( void )

module_init( hello_init );

module_exit( hello_exit );

module_license( "gpl" );

module_author( "sean depp" );

但是在說**之前, 要說一下per-cpu變數

變數, 也就是define_per_cpu( long, gusage ) = 0;這一行. 可以先看看這篇文章和這篇文章, 簡單來說就是在單cpu環境下生效的變數. 那你可能會說, 我就乙個核啊, 豈不是沒用了, 但是這是相對於虛擬cpu來說的, 也就是說, 如果你是4核8執行緒, 就可以同時有8個這樣的per-cpu變數生效. 正因為有這樣的變數, 計數變得非常簡單, 只需要統計每個cpu中的這個變數即可. 還有個問題需要解決, 那就是獲取每個cpu的基位址, 這裡又有乙個巨集for_each_online_cpu(), 只需要給個變數即可迴圈輸出活躍的cpu了. 巨集真是好東西哦~

多核情況下, 就還有乙個問題, 搶占. 當然了, 這裡的**簡單, 不關閉搶占大多數情況下也不會出錯, 但是情況複雜的話, 出錯概率就會大大提高, 甚至你不知道怎麼錯的. 而且這可是核心, 錯了往往十分致命.

preempt_disable();

pusage = this_cpu_ptr( (long *) (&gusage) );

(*pusage)++;

preempt_enable();

這裡還有乙個巨集this_cpu_ptr, 獲取per cpu變數的線性位址. 這是作業系統的知識了, 我就不多說了, 自行google咯. 那我來說一下, 為什麼要關閉搶占.

試想一下, 獲取到位址之後, 正打算++操作, 結果中斷搶占, 到了另乙個核, 之前的位址就對不上了, 這時候進行++操作就完全不對了. 所以為了不發生這樣的問題, 就需要關閉搶占, 當然, 關閉中斷也行, 但是中斷對作業系統影響太大了, 不推薦.

說了這麼多, 萬一演示不出來, 就沒有任何意義, 所以跑下程式. 編譯生成.ko, .out這些不多說了, mknod上篇文章核心必須懂(四): 撰寫核心驅動也說了. 這裡補充一下, 看到了警告, 這是缺了個庫, 最直接的解決方案就是, 安裝這個庫之後, 重編譯核心. 否則其他方案都過於麻煩.

這裡看到有8個cpu, 因為這是4核8執行緒的cpu, 然後一共跑了20次, 每個核跑的次數也可以看到. 所以, 實驗成功.

核心必須懂 二 檔案系統初探

這次來說檔案系統.檔案系統是非常重要的,提高磁碟使用率,減小磁碟磨損等等都是檔案系統要解決的問題.市面上的檔案系統也是數不勝數,比較常用的像ext4,xfs以及ntfs等等,國內的像鵝廠的tfs,然後還有sun號稱 last word in file system 的zfs,學習zfs而來的btrf...

面試必須要懂的函式

define stl ifdef stl include include using namespace std char strcpy char dest,const char src char strncpy char dest,const char src,int count int strc...

sql常用指令 必須懂的命令

學計算機的人都知道,在資料庫方面存在著各種各樣的資料庫 如mysql oracle等 有些人可能說我只有會相應的資料庫的操作介面就可以了 壓根就用不到這些指令,那我想說的是 如果你要用到幾個以上的資料庫的時候 那你都去學該資料庫的操作介面?但是資料庫都是想通的 那寫基本的操作的 是一樣的 只要我們學...