小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

使用/proc文件系統(tǒng)來訪問Linux內(nèi)核(下)

 todaytomo 2006-12-30
page 參數(shù)是這些數(shù)據(jù)寫入到的位置,其中 count 定義了可以寫入的最大字符數(shù)。在返回多頁數(shù)據(jù)(通常一頁是 4KB)時,我們需要使用 start 和 off 參數(shù)。當(dāng)所有數(shù)據(jù)全部寫入之后,就需要設(shè)置 eof(文件結(jié)束參數(shù))。與 write 類似,data 表示的也是私有數(shù)據(jù)。此處提供的 page 緩沖區(qū)在內(nèi)核空間中。因此,我們可以直接寫入,而不用調(diào)用 copy_to_user。

其他有用的函數(shù)

  我們還可以使用 proc_mkdir、symlinks 以及 proc_symlink 在 /proc 文件系統(tǒng)中創(chuàng)建目錄。對于只需要一個 read 函數(shù)的簡單 /proc 項來說,可以使用 create_proc_read_entry,這會創(chuàng)建一個 /proc 項,并在一個調(diào)用中對 read_proc 函數(shù)進行初始化。這些函數(shù)的原型如清單 8 所示。


清單 8. 其他有用的 /proc 函數(shù)
代碼:
/* Create a directory in the proc filesystem */
struct proc_dir_entry *proc_mkdir( const char *name,
                                     struct proc_dir_entry *parent );

/* Create a symlink in the proc filesystem */
struct proc_dir_entry *proc_symlink( const char *name,
                                       struct proc_dir_entry *parent,
                                       const char *dest );

/* Create a proc_dir_entry with a read_proc_t in one call */
struct proc_dir_entry *create_proc_read_entry( const char *name,
                                                  mode_t mode,
                                                  struct proc_dir_entry *base,
                                                  read_proc_t *read_proc,
                                                  void *data );

/* Copy buffer to user-space from kernel-space */
unsigned long copy_to_user( void __user *to,
                              const void *from,
                              unsigned long n );

/* Copy buffer to kernel-space from user-space */
unsigned long copy_from_user( void *to,
                                const void __user *from,
                                unsigned long n );

/* Allocate a ‘virtually‘ contiguous block of memory */
void *vmalloc( unsigned long size );

/* Free a vmalloc‘d block of memory */
void vfree( void *addr );

/* Export a symbol to the kernel (make it visible to the kernel) */
EXPORT_SYMBOL( symbol );

/* Export all symbols in a file to the kernel (declare before module.h) */
EXPORT_SYMTAB
 



通過 /proc 文件系統(tǒng)實現(xiàn)財富分發(fā)

下面是一個可以支持讀寫的 LKM。這個簡單的程序提供了一個財富甜點分發(fā)。在加載這個模塊之后,用戶就可以使用 echo 命令向其中導(dǎo)入文本財富,然后再使用 cat 命令逐一讀出。

  清單 9 給出了基本的模塊函數(shù)和變量。init 函數(shù)(init_fortune_module)負責(zé)使用 vmalloc 來為這個點心罐分配空間,然后使用 memset 將其全部清零。使用所分配并已經(jīng)清空的 cookie_pot 內(nèi)存,我們在 /proc 中創(chuàng)建了一個 proc_dir_entry 項,并將其稱為 fortune。當(dāng) proc_entry 成功創(chuàng)建之后,對自己的本地變量和 proc_entry 結(jié)構(gòu)進行了初始化。我們加載了 /proc read 和 write 函數(shù)(如清單 9 和清單 10 所示),并確定這個模塊的所有者。cleanup 函數(shù)簡單地從 /proc 文件系統(tǒng)中刪除這一項,然后釋放 cookie_pot 所占據(jù)的內(nèi)存。

  cookie_pot 是一個固定大?。?KB)的頁,它使用兩個索引進行管理。第一個是 cookie_index,標識了要將下一個 cookie 寫到哪里去。變量 next_fortune 標識了下一個 cookie 應(yīng)該從哪里讀取以便進行輸出。在所有的 fortune 項都讀取之后,我們簡單地回到了 next_fortune。


清單 9. 模塊的 init/cleanup 和變量
代碼:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <asm/uaccess.h>

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Fortune Cookie Kernel Module");
MODULE_AUTHOR("M. Tim Jones");

#define MAX_COOKIE_LENGTH       PAGE_SIZE
static struct proc_dir_entry *proc_entry;

static char *cookie_pot;  // Space for fortune strings
static int cookie_index;  // Index to write next fortune
static int next_fortune;  // Index to read next fortune


int init_fortune_module( void )
{
  int ret = 0;

  cookie_pot = (char *)vmalloc( MAX_COOKIE_LENGTH );

  if (!cookie_pot) {
    ret = -ENOMEM;
  } else {

    memset( cookie_pot, 0, MAX_COOKIE_LENGTH );

    proc_entry = create_proc_entry( "fortune", 0644, NULL );

    if (proc_entry == NULL) {

      ret = -ENOMEM;
      vfree(cookie_pot);
      printk(KERN_INFO "fortune: Couldn‘t create proc entry\n");

    } else {

      cookie_index = 0;
      next_fortune = 0;

      proc_entry->read_proc = fortune_read;
      proc_entry->write_proc = fortune_write;
      proc_entry->owner = THIS_MODULE;
      printk(KERN_INFO "fortune: Module loaded.\n");

    }

  }

  return ret;
}


void cleanup_fortune_module( void )
{
  remove_proc_entry("fortune", &proc_root);
  vfree(cookie_pot);
  printk(KERN_INFO "fortune: Module unloaded.\n");
}


module_init( init_fortune_module );
module_exit( cleanup_fortune_module );






  向這個罐中新寫入一個 cookie 非常簡單(如清單 10 所示)。使用這個寫入 cookie 的長度,我們可以檢查是否有這么多空間可用。如果沒有,就返回 -ENOSPC,它會返回給用戶空間。否則,就說明空間存在,我們使用 copy_from_user 將用戶緩沖區(qū)中的數(shù)據(jù)直接拷貝到 cookie_pot 中。然后增大 cookie_index(基于用戶緩沖區(qū)的長度)并使用 NULL 來結(jié)束這個字符串。最后,返回實際寫入 cookie_pot 的字符的個數(shù),它會返回到用戶進程。


清單 10. 對 fortune 進行寫入操作所使用的函數(shù)


  對 fortune 進行讀取也非常簡單,如清單 11 所示。由于我們剛才寫入數(shù)據(jù)的緩沖區(qū)(page)已經(jīng)在內(nèi)核空間中了,因此可以直接對其進行操作,并使用 sprintf 來寫入下一個 fortune。如果 next_fortune 索引大于 cookie_index(要寫入的下一個位置),那么我們就將 next_fortune 返回為 0,這是第一個 fortune 的索引。在將這個 fortune 寫入用戶緩沖區(qū)之后,在 next_fortune 索引上增加剛才寫入的 fortune 的長度。這樣就變成了下一個可用 fortune 的索引。這個 fortune 的長度會被返回并傳遞給用戶。

清單 11. 對 fortune 進行讀取操作所使用的函數(shù)
代碼:
int fortune_read( char *page, char **start, off_t off,
                   int count, int *eof, void *data )
{
  int len;

  if (off > 0) {
    *eof = 1;
    return 0;
  }

  /* Wrap-around */
  if (next_fortune >= cookie_index) next_fortune = 0;

  len = sprintf(page, "%s\n", &cookie_pot[next_fortune]);

  next_fortune += len;

  return len;
}




從這個簡單的例子中,我們可以看出通過 /proc 文件系統(tǒng)與內(nèi)核進行通信實際上是件非常簡單的事情?,F(xiàn)在讓我們來看一下這個 fortune 模塊的用法(參見清單 12)。


清單 12. 展示 fortune cookie LKM 的用法
代碼:
[root@plato]# insmod fortune.ko
[root@plato]# echo "Success is an individual proposition.  Thomas Watson" > /proc/fortune
[root@plato]# echo "If a man does his best, what else is there?  Gen. Patton" > /proc/fortune
[root@plato]# echo "Cats: All your base are belong to us.  Zero Wing" > /proc/fortune
[root@plato]# cat /proc/fortune
Success is an individual proposition.  Thomas Watson
[root@plato]# cat /proc/fortune
If a man does his best, what else is there?  General Patton
[root@plato]#




/proc 虛擬文件系統(tǒng)可以廣泛地用來報告內(nèi)核的信息,也可以用來進行動態(tài)配置。我們會發(fā)現(xiàn)它對于驅(qū)動程序和模塊編程來說都是非常完整的。在下面的 參考資料 中,我們可以學(xué)習(xí)到更多相關(guān)知識。

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多