关于sysctl系统调用
时间:2010-07-02 来源:tianchunlong
sysctl系统调用用于读写内核参数,比如主机名,最大可打开的文件数目等等的信息。其函数原型是:
#include <unistd.h>
#include <linux/unistd.h>
#include <linux/sysctl.h>
_syscall1(int, _sysctl, struct __sysctl_args *, args);
int _sysctl(struct __sysctl_args *args);
syscall1是一个宏,展开为一个嵌入汇编函数,用于定义_sysctl函数,具体不再展开。关于内核参数的具体项及其值,我们可以查看 /proc/sys目录(如果内核配置了CONFIG_PROC_FS的话)。以下是我的机器上/proc/sys内容(全部为目录项):
debug dev fs kernel net proc sunrpc vm
一个目录代表一种类型的内核参数,比如fs目录下全部是文件系统相关的内核参数,而net下则全部是网络相关的内核参数。在这些目录下还有子目录,比如net目录下:
core ethernet ipv4 ipv6 token-ring unix
所有的内核参数在/proc/sys形成一个树状结构。
以上是内核参数在/proc/sys目录下的表示,对于这些参数,最简单地,我们通过文件系统的基本操作就可完成对其的读写。下面讲讲这些参数在内核代码中的表示以及相应地如何通过sysctl系统调用在内核代码中进行读写。
在内核中,这个树状结构的每个节点(包括枝节点和叶节点)都是通过一个结构体struct ctl_table来表示的,每个节点都有一个数值型的ID,来唯一标识这个节点,因为是树状结构,所以这个ID不必唯一,但通过ID从根节点开始的搜索路径必须唯一。同时,每个节点都有一个文本ID,就是该节点在/proc/sys中的目录名(文件名)。同时,有一个指向子节点的指针。
root_table[]是一个数组,含有所有第一级子目录节点。第一级子目录节点对应的数组分别是:kern_table[],vm_table[], net_table[],proc_table[],fs_table[],debug_table[],dev_table[]。
所有的这些数组(包括你将要新添加的数组)都以一个list的形式组织在一个变量root_table_header中。 root_table_header不体现树型结构,树型结构是通过struct ctl_table的指向子节点的指针,或者数组中的root_dir项来体现。
我们现在看一下kern_table[]数组中的两个子节点:ostype,osrelease。在/proc/sys目录中,我们可以直接得到它们的文件内容,在我的安装有FC3的系统中,得到内容如下:
[helq@localhost kernel]$ cat osrelease
2.6.12-1.1381_FC3
[helq@localhost kernel]$ cat ostype
Linux
这两个子节点的数值型ID分别是:KERN_OSTYPE,KERN_OSRELEASE,它们的父节点的数值型ID是CTL_KERN。我们通过sysctl系统调用得到这两个值的代码如下:
#include <linux/unistd.h>
#include <linux/types.h>
#include <linux/sysctl.h>
#include <stdio.h>
_syscall1(int, _sysctl, struct __sysctl_args *, args);
int sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
void *newval, size_t newlen)
{
struct __sysctl_args args={name,nlen,oldval,oldlenp,newval,newlen};
return _sysctl(&args);
}
#define SIZE(x) sizeof(x)/sizeof(x[0])
#define OSNAMESZ 100
#define OSRELEASESZ 256
char osname[OSNAMESZ];
char osrelease[OSRELEASESZ];
int osnamelth;
int name[] = { CTL_KERN, KERN_OSTYPE };
int osreleaseth;
int release[] = { CTL_KERN, KERN_OSRELEASE };
main(){
osnamelth = sizeof(osname);
if (sysctl(name, SIZE(name), osname, &osnamelth, 0, 0)){
perror("sysctl");
return -1;
}
osreleaseth = sizeof(osrelease);
if(sysctl(release, SIZE(release), osrelease, &osreleaseth, 0, 0)){
perror("sysctl");
return -1;
}
printf("This machine is running %s %s\n", osname, osrelease);
return 0;
}
下面是在安装有FC5的虚拟机上的运行结果:
This machine is running Linux 2.6.16-1.2080_FC5.stk16
sysctl系统调用调用到的内核函数是sys_sysctl,该函数调用do_sysctl,do_sysctl首先检查struct __sysctl_args.nlen的值,保证树的深度不超过10,然后通过调用parse_table函数,匹配root_table_header 中每一个数组的每一项的ctl_name,匹配到后,会通过ctl_table.child指针,进行子项的逐步匹配。
如果匹配完成,则结构体struct ctl_table有一个成员函数strategy会被调用到(如果存在),以上面的例子程序为例,该程序取操作系统的类型与版本,都是字符型数据,所以在叶子节点KERN_OSTYPE, KERN_OSRELEASE上都有strategy成员存在,其作用是把struct ctl_table.data中的节点数据保存到传入的参数oldval中,并把传入的参数newval保存到struct ctl_table.data中(如果需要的话),因为非叶节点是没有数据的,所以非员节点的strategy成员值为NULL。
匹配完成后,最后的读写在do_sysctl_strategy中完成。
#include <unistd.h>
#include <linux/unistd.h>
#include <linux/sysctl.h>
_syscall1(int, _sysctl, struct __sysctl_args *, args);
int _sysctl(struct __sysctl_args *args);
syscall1是一个宏,展开为一个嵌入汇编函数,用于定义_sysctl函数,具体不再展开。关于内核参数的具体项及其值,我们可以查看 /proc/sys目录(如果内核配置了CONFIG_PROC_FS的话)。以下是我的机器上/proc/sys内容(全部为目录项):
debug dev fs kernel net proc sunrpc vm
一个目录代表一种类型的内核参数,比如fs目录下全部是文件系统相关的内核参数,而net下则全部是网络相关的内核参数。在这些目录下还有子目录,比如net目录下:
core ethernet ipv4 ipv6 token-ring unix
所有的内核参数在/proc/sys形成一个树状结构。
以上是内核参数在/proc/sys目录下的表示,对于这些参数,最简单地,我们通过文件系统的基本操作就可完成对其的读写。下面讲讲这些参数在内核代码中的表示以及相应地如何通过sysctl系统调用在内核代码中进行读写。
在内核中,这个树状结构的每个节点(包括枝节点和叶节点)都是通过一个结构体struct ctl_table来表示的,每个节点都有一个数值型的ID,来唯一标识这个节点,因为是树状结构,所以这个ID不必唯一,但通过ID从根节点开始的搜索路径必须唯一。同时,每个节点都有一个文本ID,就是该节点在/proc/sys中的目录名(文件名)。同时,有一个指向子节点的指针。
root_table[]是一个数组,含有所有第一级子目录节点。第一级子目录节点对应的数组分别是:kern_table[],vm_table[], net_table[],proc_table[],fs_table[],debug_table[],dev_table[]。
所有的这些数组(包括你将要新添加的数组)都以一个list的形式组织在一个变量root_table_header中。 root_table_header不体现树型结构,树型结构是通过struct ctl_table的指向子节点的指针,或者数组中的root_dir项来体现。
我们现在看一下kern_table[]数组中的两个子节点:ostype,osrelease。在/proc/sys目录中,我们可以直接得到它们的文件内容,在我的安装有FC3的系统中,得到内容如下:
[helq@localhost kernel]$ cat osrelease
2.6.12-1.1381_FC3
[helq@localhost kernel]$ cat ostype
Linux
这两个子节点的数值型ID分别是:KERN_OSTYPE,KERN_OSRELEASE,它们的父节点的数值型ID是CTL_KERN。我们通过sysctl系统调用得到这两个值的代码如下:
#include <linux/unistd.h>
#include <linux/types.h>
#include <linux/sysctl.h>
#include <stdio.h>
_syscall1(int, _sysctl, struct __sysctl_args *, args);
int sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
void *newval, size_t newlen)
{
struct __sysctl_args args={name,nlen,oldval,oldlenp,newval,newlen};
return _sysctl(&args);
}
#define SIZE(x) sizeof(x)/sizeof(x[0])
#define OSNAMESZ 100
#define OSRELEASESZ 256
char osname[OSNAMESZ];
char osrelease[OSRELEASESZ];
int osnamelth;
int name[] = { CTL_KERN, KERN_OSTYPE };
int osreleaseth;
int release[] = { CTL_KERN, KERN_OSRELEASE };
main(){
osnamelth = sizeof(osname);
if (sysctl(name, SIZE(name), osname, &osnamelth, 0, 0)){
perror("sysctl");
return -1;
}
osreleaseth = sizeof(osrelease);
if(sysctl(release, SIZE(release), osrelease, &osreleaseth, 0, 0)){
perror("sysctl");
return -1;
}
printf("This machine is running %s %s\n", osname, osrelease);
return 0;
}
下面是在安装有FC5的虚拟机上的运行结果:
This machine is running Linux 2.6.16-1.2080_FC5.stk16
sysctl系统调用调用到的内核函数是sys_sysctl,该函数调用do_sysctl,do_sysctl首先检查struct __sysctl_args.nlen的值,保证树的深度不超过10,然后通过调用parse_table函数,匹配root_table_header 中每一个数组的每一项的ctl_name,匹配到后,会通过ctl_table.child指针,进行子项的逐步匹配。
如果匹配完成,则结构体struct ctl_table有一个成员函数strategy会被调用到(如果存在),以上面的例子程序为例,该程序取操作系统的类型与版本,都是字符型数据,所以在叶子节点KERN_OSTYPE, KERN_OSRELEASE上都有strategy成员存在,其作用是把struct ctl_table.data中的节点数据保存到传入的参数oldval中,并把传入的参数newval保存到struct ctl_table.data中(如果需要的话),因为非叶节点是没有数据的,所以非员节点的strategy成员值为NULL。
匹配完成后,最后的读写在do_sysctl_strategy中完成。
相关阅读 更多 +
排行榜 更多 +

<img preview="http://pic.pdowncc.com/uploadimg/ico/2025/0523/1747993424374100.png" width="32" height="32" src="http://pic.pdowncc.com/uploadimg/ico/2025/0523/1747993424374100.png" alt="弓箭勇者最新版" />
飞行射击 下载
<img preview="http://pic.pdowncc.com/uploadimg/ico/2025/0523/1747993424374100.png" width="32" height="32" src="http://pic.pdowncc.com/uploadimg/ico/2025/0523/1747993424374100.png" alt="弓箭勇者最新版" />
飞行射击 下载
<img preview="http://pic.pdowncc.com/uploadimg/ico/2025/0523/1747993424374100.png" width="32" height="32" src="http://pic.pdowncc.com/uploadimg/ico/2025/0523/1747993424374100.png" alt="弓箭勇者最新版" />
飞行射击 下载- 4 <img preview="http://pic.pdowncc.com/uploadimg/ico/2025/0523/1747993424374100.png" width="32" height="32" src="http://pic.pdowncc.com/uploadimg/ico/2025/0523/1747993424374100.png" alt="弓箭勇者最新版" />下载73.78MB · 96℃
1970-01-01
- 5 <img preview="http://pic.pdowncc.com/uploadimg/ico/2025/0523/1747993424374100.png" width="32" height="32" src="http://pic.pdowncc.com/uploadimg/ico/2025/0523/1747993424374100.png" alt="弓箭勇者最新版" />下载43.7 MB · 99℃
1970-01-01
- 6 <img preview="http://pic.pdowncc.com/uploadimg/ico/2025/0523/1747993424374100.png" width="32" height="32" src="http://pic.pdowncc.com/uploadimg/ico/2025/0523/1747993424374100.png" alt="弓箭勇者最新版" />下载110.69MB · 96℃
1970-01-01