2016-06-21 27 views
0

我正在更新我們的內核驅動程序以在Ubuntu 16.0.4上使用Linux內核4.4.0。最後的驅動程序使用linux內核3.9.2。 在其中一個模塊中,我們創建了一個procfs條目來讀取/寫入板載風扇監視值。風扇監控用於讀取/寫入CPU或GPU溫度/調製等。值。如何替換返回EOF和字節數讀取的procfs條目的讀取函數?

使用以下API創建的procfs項的模塊:

struct proc_dir_entry *create_proc_entry(const char *name, umode_t 
mode,struct proc_dir_entry *parent); 

是這樣的:現在

struct proc_dir_entry * proc_entry = 
create_proc_entry("fmon_gpu_temp",0644,proc_dir); 
proc_entry->read_proc = read_proc; 
proc_entry->write_proc = write_proc; 

,該read_proc實現東西是這樣的:

static int read_value(char *buf, char **start, off_t offset, int count, int *eof, void *data) { 
    int len = 0; 
    int idx = (int)data; 

    if(idx == TEMP_FANCTL) 
     len = sprintf (buf, "%d.%02d\n", fmon_readings[idx]/TEMP_SAMPLES, 
       fmon_readings[idx] % TEMP_SAMPLES * 100/TEMP_SAMPLES); 
    else if(idx == TEMP_CPU) { 
     int i; 
     len = sprintf (buf, "%d", fmon_readings[idx]); 
     for(i=0; i < FCTL_MAX_CPUS && fmon_cpu_temps[i]; i++) { 
      len += sprintf (buf+len, " CPU%d=%d",i,fmon_cpu_temps[i]); 
     } 
     len += sprintf (buf+len, "\n"); 
    } 
    else if(idx >= 0 && idx < READINGS_MAX) 
     len = sprintf (buf, "%d\n", fmon_readings[idx]); 
    *eof = 1; 
    return len; 
} 

這個讀取函數肯定假設用戶提供了足夠的緩衝空間來存儲t他的溫度值。這在用戶空間程序中正確處理。而且,對於每次調用此函數,讀取值都是全部的,因此對於相同的溫度值,不需要支持/需要後續讀取。 另外,如果我在shell的這個procfs入口上使用「cat」程序,'cat'程序正確顯示了這個值。我認爲通過將EOF設置爲true並返回讀取字節數來支持這一點。

新的Linux內核不再支持這個API。

我的問題是:

我怎麼能這個API更改爲新的procfs的API結構保持功能一樣:每次讀取應返回的值,程序「貓」也應該很好地工作,而不是進入無限循環?

回答

1

用於在Linux上讀取文件的主用戶界面read(2)。它的內核空間對是.read函數,在struct file_operations

在內核空間(read_procseq_file等)讀取文件中的其它機制實際上是一個(參數化)實現.read功能。

內核將EOF指示符返回給用戶空間的唯一方法是返回0作爲讀取的字節數。

即使read_proc對於3.9內核的實現實際上實現eof標誌在下次調用時返回0。並且cat實際上執行了第二個調用read以發現文件結束。

(此外,cat執行超過2讀的調用:先用1作爲計數,第二與計數等於頁面大小減1,並且最後與其餘計數。)

「一次性」讀取實現的最簡單方法是使用seq_file in single_open() mode。

+0

我已經在問題中添加了讀取函數的實現。我知道我可以從用戶空間多次調用讀取函數,並且每次獲得更新的溫度值。對 ? 此外,這裏沒有文件偏移,因此每次調用這裏讀取就像讀取一個變量。程序'貓'沒有進入無限循環就可以正常工作。 – Monku

+0

對我來說,問題是如何實現與新內核API類似的東西。也就是說,我應該可以打開單個文件多次調用讀取。如果我將seq_file與single_open一起使用,那麼在第二次調用讀取之前,我將不得不關閉文件,對吧? – Monku

+1

'如果我使用seq_file與single_open,我將不得不在第二次打電話之前關閉文件,對吧?' - 是的,當文件被讀取到EOF時,您需要在重新讀取之前重置讀取位置。它可以通過文件重新打開('close()'+'open()')或者使用'lseek()'到0來完成。但'single_open()'並不意味着你可能只打印單個值來輸出:在'.show'函數內部,你可以執行類似於'read_proc'中的循環。但更好的方法是用'seq_open()'而不是'single_open()'使用完整的'seq_file'功能。 – Tsyvarev