1. 程式人生 > >linux 2.6.32下sysctl的使用

linux 2.6.32下sysctl的使用

struct ctl_table 
{
    int ctl_name;                   /* 結點標識,同一層的結點用不同的數字來標識
                                                 此處設定的意義可以看do_sysctl()->parse_table()
                                             */          
    const char *procname;        /* /proc/sys/ 下使用的檔名*/
    void *data;                            /*核心變數的地址*/
    int maxlen;                            /*核心變數的尺寸大小*/
    mode_t mode;                            /*檔案訪問許可權*/
    struct ctl_table *child;                /*建立檔案與目錄的父子關係*/
    struct ctl_table *parent;              /* Automatically set */
    proc_handler *proc_handler;    /* 當對檔案讀取或寫入的時候 呼叫此函式  
                                                             根據值的型別 初始化為不同的函式如字串 proc_dostring()
                                                         */
    ctl_handler *strategy;                 /* 用sysctl系統呼叫的時候 此函式被呼叫 sysctl_string()*/
    void *extra1;
    void *extra2;                               /*extra1 extra2可選引數 通常定義變數的最小值 或最大值*/
};

struct ctl_table_header *register_sysctl_table(struct ctl_table *table)
fun:註冊sysctl(/proc/sys)下的操作項 
標頭檔案:#include <linux/sysctl.h>

void unregister_sysctl_table(struct ctl_table_header * header)
fun:登出sysctl(/proc/sys)下的操作項 
標頭檔案:#include <linux/sysctl.h>

 

初始化ctl_table{}->proc_handler的函式

proc_dostring()

讀寫一個字串

proc_dointvec()

讀寫包含一個或多個整數的陣列

proc_dointvec_minmax()

類似 proc_dointvec() 但是要確定輸入資料是在 min/max範圍內

proc_dointvec_jiffies ()

讀寫整形陣列 此核心變數以jiffies為單位表示,返回給使用者前先轉為秒數

proc_doulongvec_minmax()

類似proc_dointvec_minmax()但讀取的是長整形

proc_doulongvec_ms_jiffies_minmax()

讀寫長整形陣列 此核心變數以jiffies為單位 返回給使用者前先轉換為毫秒數

 

初始化ctl_table{}-> strategy的函式

sysctl_string()

讀寫一個字串

sysctl_intvec()

讀寫一個整形陣列 而且確定其值符合min/max

sysctl_jiffies()

讀寫一個以jiffies表示的值,然後將其轉化為秒

sysctl_ms_jiffies()

讀寫一個以jiffies表示的值,然後把它裝化為毫秒

 

舉個栗子

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/sysctl.h>

int g_catsize=20;
int g_catcolor = 10;
char g_catname[258] = {"miaomiao"};

enum{
    KERNEL_CAT_SIZE=1,//不要從0開始
    KERNEL_CAT_COLOR,
    KERNEL_CAT_NAME
};

enum{
   KERNEL_CAT = CTL_CPU + 11,//不要從0開始 不要和系統已有的ctl_name重複 why?看do_sysctl()->parse_table()
};

int my_proc_dointvec(struct ctl_table *table, int write,
		   void __user *buffer, size_t *lenp, loff_t *ppos)
{
     int ret = 0; 
     
	 //用來處理整型資料或整型陣列
     ret = proc_dointvec(table,write,buffer,lenp,ppos);
     printk("*********************catsize=%d catcolor=%d\n",g_catsize,g_catcolor);

     return ret;
}

int my_proc_dostring(struct ctl_table *table, int write,
		  void __user *buffer, size_t *lenp, loff_t *ppos)
{
     int ret; 
	 //用來處理字串
     ret = proc_dostring(table,write,buffer,lenp,ppos);
     printk("**************************catname=%s\n",g_catname);
     return ret;
}

/*對應的檔案項
 * /proc/sys/mycat1/catsize
   /proc/sys/mycat1/catcolor
   /proc/sys/mycat1/catname
 * */
static ctl_table  cat_attr_table[]={
    {
        .ctl_name = KERNEL_CAT_SIZE,
        .procname = "catsize",
        .data = &g_catsize,
        .maxlen = sizeof(int),
        .mode = 0644,
        .proc_handler = &my_proc_dointvec  //處理整型
    },
   { 
       .ctl_name = KERNEL_CAT_COLOR,
       .procname = "catcolor",
       .data = &g_catcolor,
       .maxlen = sizeof(int),
       .mode = 0644,
       .proc_handler = &my_proc_dointvec  //處理整型
   }, 
  {
       .ctl_name = KERNEL_CAT_NAME,
       .procname = "catname",
       .data = g_catname,
       .maxlen = 256,
       .mode = 0644,
       .proc_handler = &my_proc_dostring//處理字串
        
  },
  {}  //最後一項必須為空
};

/*
對應的目錄項:
/proc/sys/mycalt1/ 
*/
static ctl_table  mycat[]={
    {
      .ctl_name = KERNEL_CAT,
      .procname = "mycat1",
      .mode = 0555, //建立目錄許可權
      .child = cat_attr_table //設定子檔案項
    },
   {}  //最後一項必須為空	
};

static struct ctl_table_header *cat_table_header;

static int __init  test_init(void)
{  
   //註冊sysctl操作項
   cat_table_header = register_sysctl_table(mycat);     
   if(NULL == cat_table_header)
   {
       printk("register error\n");
       return -1; 
   } 
    return 0;
}

static void __exit test_exit(void)
{
	//登出syscatl操作項 
    unregister_sysctl_table(cat_table_header);
    return;
}

module_init(test_init);
module_exit(test_exit);

MODULE_LICENSE("GPL");