随着AIX®Version 5.3的推出,以及Power体系结构的快速改进及其在* nix市场的增长,全球开发人员对AIX的兴趣日益浓厚。 本文可帮助您开始在AIX上开发自己的内核扩展。
AIX内核提供了使用内核扩展来动态扩展其功能的接口。 内核扩展是添加到内核以扩展其功能的例程。 内核扩展是AIX内核体系结构的重要组成部分,它们类似于其他平台(例如Linux®)上可动态加载的模块,这些模块可向正在运行的内核中添加功能,而无需重新启动计算机。
内核扩展在内核保护域中运行。 例如,如果您需要创建自己的系统调用,内核进程或文件系统,则可能需要内核扩展。 内核扩展以与内核相同的模式运行。 如果内核以64位模式运行,则扩展也必须能够以该模式运行。
本文适用于希望在AIX上编写自己的内核扩展的任何人。 只需要对UNIX®编程有基本的了解。
术语kernext有时用作内核扩展的缩写,尤其是在代码中。
关于内核扩展
为扩展AIX内核而添加的例程可能属于以下类别:
系统调用 虚拟文件系统 内核扩展和设备驱动程序管理内核服务 设备驱动程序
无论例程属于哪种类别,它们都称为内核扩展。
内核扩展的生命周期分为以下几个阶段,包括:
加载-此阶段将内核扩展加载到内核内存中。 执行-此阶段开始执行内核扩展并调用其入口点。 这是初始化。 通讯-此阶段与内核扩展通讯。 现在,内核扩展正在执行其工作。 终止-此阶段终止内核扩展。 卸载-这将从内存中卸载内核扩展。
sysconfig()系统调用用于控制这些阶段。 sysconfig(需要超级用户特权,它是管理内核扩展的主要应用程序编程接口(API)。其声明为:
int sysconfig( (Defined in /usr/include/sys/sysconfig.h )
int cmd, /* function requested: load, unload, etc */
void *parmp, /* addr of struct containing info for cmd */
int parmlen /* length of parmp information */
);
sysconfig()采用命令(cmd)参数,该参数选择调用者所需的操作。
下表1列出了一些常见的操作。 有关详尽的列表,请参见/usr/include/sys/sysconfig.h 。
表1.常见操作
行动 描述
*)SYS_KLOAD 将内核扩展对象文件加载到内核内存中。 *)SYS_SINGLELOAD 仅在尚未加载内核扩展对象文件时加载。 *)SYS_QUERYLOAD 确定是否加载了指定的内核目标文件。 *)SYS_KULOAD 卸载先前加载的内核目标文件。 *)SYS_CFGKMOD 为了配置目的,在其模块入口点调用指定的模块。
您可以使用自己的自定义命令代码,前提是要妥善处理。 您也可以使用strload命令加载或卸载内核扩展。 通常,您必须编写自己的代码才能加载内核扩展。
让我们看一下其中涉及的一些重要结构:
Struct cfg_load
加载或卸载内核扩展时,此结构将传递给sysconfig() 。 该结构在/usr/include/sys/sysconfig.h中定义为:
struct cfg_load
{
caddr_t path; /* ptr to object module pathname */
caddr_t libpath; /* ptr to a substitute libpath */
mid_t kmid; /* kernel module id (returned) */
};
struct cfg_load的结构成员为:
path此命令指定内核扩展模块的目标文件的路径名。 libpath此命令是要搜索内核扩展目标文件的路径。 如果此字段为null,则使用path字段。 Kmid此命令包含内核模块ID。 根据选项,您传递给sysconfig() 。 它要么由sysconfig()填充,要么必须传递给sysconfig( ) 。
调用模块入口点时, Struct cfg_kmod结构将传递给sysconfig( ) 。 Struct cfg_kmod在/usr/include/sys/sysconfig.h中定义为:
struct cfg_kmod {
mid_t kmid; /* module ID of module to call */
int cmd; /* command parameter for module */
caddr_t mdiptr; /* pointer to module dependent info */
int mdilen; /* length of module dependent info */
};
cfg_kmod的结构成员为:
kmid此命令指定内核扩展模块ID,该ID在加载模块后返回。 cmd此命令指定模块的命令。 可以是用户定义的值,也可以取自<sys / device.h>,如下面的示例所示。 mdiptr此命令用于将数据传递到内核扩展。 mdilen此命令包含在mdiptr传递的数据的长度。
现在,让我们继续进行一些切实的工作。
Hello World内核扩展
现在,您应该可以开始编写一个简单的“ Hello World”内核扩展了。 您将编写两个程序:
控制器应用程序 ,用于控制和配置内核扩展 实际的Hello World内核扩展
要编译Hello World内核扩展的示例代码,只需在复制源代码的目录中键入make 。 出于明显的安全原因,只有root用户才能加载或卸载内核扩展。 由于加载的代码以内核模式运行,因此它可以完全访问系统上的所有内容。 因此,即使是root拥有的setuid程序也不足以加载内核扩展-您必须以root用户身份登录。 请参见下面的清单1 。
清单1.控制器应用程序:kctrl.c
1 /* Controller App */
2
3 #include <stdio.h>
4 #include <errno.h>
5 #include <string.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <sys/sysconfig.h>
9 #include <sys/device.h>
10
11 int main(int argc, char *argv[])
12 {
13 struct cfg_kmod opt_kmod;
14 struct cfg_load opt_load, query_load;
15 struct stat statbuf;
16 char szKernExt[256], c;
17
18 /* Check if the user has appropriate privileges */
19 if (getuid() != 0) {
20 fprintf(stderr, " Not SuperUser.\n");
21 exit(EACCES);
22 }
23
24 /* Check arguments */
25 if (argc != 2) {
26 printf ("Usage: %s <kernel_extension>\n", argv[0]);
27 exit(EINVAL);
28 }
29
30 strcpy(szKernExt,argv[1]);
31
32 /* Check existence of file */
33 if (stat(szKernExt,&statbuf) != 0) {
34 perror("stat");
35 exit(errno);
36 }
37
38 /* Fill up the cfg_load structure */
39 opt_load.path = szKernExt; /* file name */
40 opt_load.libpath = NULL; /* no library */
41 opt_load.kmid = 0;
42
43 /* Perform various operations on the kernel extension */
44 while(1) {
45
46 fprintf (stderr, "\n Enter choice, (l)oad, (u)nload, (i)nit, (t)erm,
(q)uery or (e)nd\n");
47
48 while((c = getchar()) < 'a' && c > 'z') ; /* discard garbage */
49
50 switch(c) {
51
52 case 'l': /* load a kernel extension */
53
54 /* load kernel extension request */
55 if (sysconfig(SYS_KLOAD,&opt_load,sizeof(struct cfg_load)))
56 perror("sysconfig(SYS_KLOAD)"); /* print error message */
57 else /* otherwise */
58 printf("Extension Successfully loaded, kmid is %d\n", opt_load.kmid);
59
60 break;
61
62 case 'i': /* Initialize a KernExt */
63
64 /* Initialize the kernel extension */
65 opt_kmod.kmid = opt_load.kmid;
66 opt_kmod.cmd = CFG_INIT;
67 opt_kmod.mdiptr = NULL;
68 opt_kmod.mdilen = 0;
69 if (sysconfig(SYS_CFGKMOD,&opt_kmod,sizeof(struct cfg_kmod)))
70 perror("sysconfig(SYS_CFGKMOD)"); /* print error message */
71 else
72 printf(" Extension Initialized \n");
73
74 break;
75
76 /* Unload kernel extension */
77 case 'u':
78 /* Check if KernExt is loaded */
79 if (opt_load.kmid == 0)
80 printf("kernel Extension not loaded\n");
81 else {
82 if (sysconfig(SYS_KULOAD,&opt_load,sizeof(struct cfg_load)))
83 perror("sysconfig(SYS_KULOAD)");
84 else
85 fprintf(stderr, "KernExt Successfully Unloaded \n");
86 }
87
88 break;
89
90 /* Terminate the kernel extension */
91 case 't':
92
93 /* Check if KernExt is loaded */
94 if (opt_load.kmid == 0)
95 fprintf(stderr, "Extension not loaded\n");
96 else {
97 opt_kmod.kmid = opt_load.kmid;
98 opt_kmod.cmd = CFG_TERM; /* Terminate the kernel extension */
99 opt_kmod.mdiptr = NULL;
100 opt_kmod.mdilen = 0;
101 if (sysconfig(SYS_CFGKMOD,&opt_kmod,sizeof(struct cfg_kmod)))
102 perror("sysconfig(SYS_CFGKMOD)"); /* print error */
103 else
104 fprintf(stderr, " KernExtension Terminated \n");
105 }
106
107 break;
108
109
110 /* query kernel extension existence */
111 case 'q':
112
113 query_load.path = opt_load.path;
114 query_load.libpath = opt_load.libpath ;
115 query_load.kmid = 0;
116
117 if (sysconfig(SYS_QUERYLOAD,&query_load,sizeof(struct cfg_load)))
118 perror("sysconfig(SYS_QUERYLOAD)");
119 else
120 {
121 if(query_load.kmid > 0)
122 fprintf(stderr, " Extension is loaded, with kmid %d \n",
query_load.kmid);
123 else
124 fprintf(stderr, " Extension is not loaded \n");
125 }
126
127 break; /* done */
128
129
130 case 'e':
131 exit(0);
132
133
134 default:
135 fprintf(stderr, "Incorrect option \n");
136 break;
137 }
138 getchar();
139 }
140
141 return 0;
142 }
现在,您需要定义类型的变量,尤其是struct cfg_kmod和struct cfg_load 。
struct cfg_kmod opt_kmod;
struct cfg_load opt_load, query_load;
加载内核扩展
最初,要加载内核扩展,您需要使用SYS_KLOAD命令参数调用sysconfig 。 您将opt_load和sizeof(struct cfg_load)传递为:
sysconfig(SYS_KLOAD,&opt_load,sizeof(struct cfg_load))
成功调用sysconfig ,您将获得kmid ,该kmid将被打印在屏幕上。
您用内核扩展的路径填充cfg_load结构:
opt_load.path = szKernExt;
您将libpath设置为NULL因为在这种情况下,您不依赖于任何非系统定义的库:
opt_load.libpath = NULL;
您将kmid字段初始化为零:
opt_load.kmid = 0;
执行代码,如下所示:
[root@aix1] ./kctrl ./kernext_hello
Enter choice, (l)oad, (u)nload, (i)nit, (t)erm, (q)uery or (e)nd
l
Extension Successfully loaded, kmid is 49033924
您可以使用genkex命令查看系统上已加载的内核扩展的列表:
[root@aix1] genkex
Text address Size File
2ec3000 2d8 ./kernext_hello
<Snip>
初始化内核扩展
加载内核扩展后,您可以使用CFG_INIT命令调用sysconfig( )来调用其入口点。
控制器应用程序使用sysconfig()例程。 填写struct cfg_kmod opt_kmod ,如下所示:
opt_kmod.kmid = opt_load.kmid;
opt_kmod.cmd = CFG_INIT;
opt_kmod.mdiptr = NULL;
opt_kmod.mdilen = 0;
您将在kmid字段中填充内核扩展的标识符,该标识符是您先前对sysconfig( )调用获得的。
CFG_INIT命令调用内核扩展的入口点。 目前,您尚未将任何参数传递给内核扩展,因此, mdiptr为NULL 。 Mdilen包含的长度mdiptr 。
在示例内核扩展中,我们添加了在syslog文件中打印输出的例程。 检查系统上的syslog输出; 它的输出应该类似于以下内容:
Apr 3 08:22:40 aix1 kern:debug unix: Enter hello_init:: command = 0x1
Apr 3 08:22:40 aix1 kern:debug unix: Initializing Hello World KernExt
查询内核扩展
您可以使用struct cfg_load查询扩展是否已加载。 您可以使用query_load变量执行此操作。
现在,在从所述可变opt_load和呼叫的路径和LIBPATH值填补sysconfig与命令SYS_QUERYLOAD ,如下图所示:
query_load.path = opt_load.path;
query_load.libpath = opt_load.libpath ;
query_load.kmid = 0;
如果内核扩展被加载, kmid场有kmid内核扩展,这始终是大于零的。 如下所示,您将获得内核扩展的kmid :
[root@aix1] ./kctrl ./kernext_hello
Enter choice, (l)oad, (u)nload, (i)nit, (t)erm, (q)uery or (e)nd
q
Extension is loaded, with kmid 49033924
终止内核扩展
要终止内核扩展,请使用struct cfg_kmod嵌入的CFG_TERM命令调用sysconfig() 。 然后,使用值填充opt_kmod变量,如下所示:
opt_kmod.kmid = opt_load.kmid;
opt_kmod.cmd = CFG_TERM;
opt_kmod.mdiptr = NULL;
opt_kmod.mdilen = 0;
现在,您有了kmid ,可以将命令填写为CFG_TERM ,如下所示:
[root@aix1] ./kctrl ./kernext_hello
Enter choice, (l)oad, (u)nload, (i)nit, (t)erm, (q)uery or (e)nd
t
KernExtension Terminated
在syslog输出中,您将看到以下几行:
Apr 3 08:22:43 fsaix9 kern:debug unix: Enter hello_init:: command = 0x2
Apr 3 08:22:43 fsaix9 kern:debug unix: Terminating Hello World KernExt
卸载内核扩展
要卸载内核扩展,请使用SYS_KULOAD参数调用sysconfig并传递struct cfg_load ,其中已填充path和kmid字段,如下所示:
sysconfig(SYS_KULOAD,&opt_load,sizeof(struct cfg_load)
要卸载内核扩展,请使用选项“ u”并选择Enter ,如下所示:
[root@aix1] ./kctrl ./kernext_hello
Enter choice, (l)oad, (u)nload, (i)nit, (t)erm, (q)uery or (e)nd
u
KernExt Successfully Unloaded
使用sysconfig()要小心; kmid错误值可能会使系统崩溃(请参见清单2 )。
清单2. Hello World内核扩展:kernext_hello.c
1 /* A Hello World Kernel Extension */
2 #include <errno.h>
3 #include <syslog.h>
4 #include <sys/device.h>
5
6
7
8 int hello_init(int cmd, struct uio *uio)
9 {
10
11 bsdlog(LOG_DEBUG | LOG_KERN, "Enter hello_init::Ã?? command = 0x%x \ n",cmd);
12
13 if (cmd == CFG_INIT)
14 bsdlog(LOG_DEBUG | LOG_KERN, " Initializing Hello World KernExt \n");
15 else if (cmd == CFG_TERM)
16 bsdlog(LOG_DEBUG | LOG_KERN, " Terminating Hello World KernExt \n");
17 else
18 bsdlog(LOG_DEBUG | LOG_KERN, " Unknown command to Adv KernExt \n");
19
20
21 return 0;
22 }
内核扩展没有main()例程; 而是有一个入口点,当使用SYS_CFGKMOD和sysconfig()发出CFG_INIT命令时,控制器应用程序将调用该入口点。
在内核扩展示例中,您只有一个函数,即内核扩展入口点,它是hello_init() 。 入口点有两个参数和一个整数,即从sysconfig()传递的命令参数,该参数嵌入在struct cfg_kmod 。 另一个参数是struct uio ,它用于将数据传递到内核扩展。 在Hello World kernext中,您没有使用struct uio ,如上一节所示。
默认情况下,入口点的名称需要为__start( ) 。 如果您指定其他名称(在这种情况下),则在构建内核扩展时需要指定该名称。
Hello World内核扩展确认收到命令,然后将其打印出来。 它使用bdslog()进行打印。 bsdlog的第一个参数是优先级。 您将两个标志用作优先级:
LOG_DEBUG,告诉syslog这是一条调试消息 LOG_KERN,告诉系统日志此消息来自内核
要获取日志消息,请确保已配置syslogd 。
例如,在/etc/syslog.conf中,您可以添加以下内容:
*.debug /tmp/syslog.out rotate size 100k files 4
然后ps â????aef | grep syslog ps â????aef | grep syslog ,并kill â????HUP它– kill â????HUP 。
下面清单3中的构建过程是Hello World内核扩展的Makefile。
清单3. Hello World内核扩展的Makefile
1 all: kernext_hello kctrl
2
3 kctrl: kctrl.c
4 cc -o kctrl kctrl.c
5
6
7 kernext_hello: kernext_hello.c
8 cc -q32 -o kernext_hello32.o -c kernext_hello.c
9 ld -b32 -o kernext_hello32 kernext_hello32.o -e hello_init
-bI:/usr/lib/kernex.exp -lsys -l csys
10 cc -q64 -o kernext_hello64.o -c kernext_hello.c
11 ld -b64 -o kernext_hello64 kernext_hello64.o -e hello_init
-bI:/usr/lib/kernex.exp -lsys -l csys
12 rm -f kernext_hello
13 ar -X32_64 -r -v kernext_hello kernext_hello32 kernext_hello64
14
15 clean:
16 rm -f *.o kernext_hello kernext_hello32 kernext_hello64 kctrl 2> /dev/null
在Makefile中,您有两个目标:控制器应用程序和Hello World内核扩展。
控制器应用程序的命令非常简单,您可以使用-o选项指定目标文件:
4 cc -o kctrl kctrl.c
构建内核扩展
内核扩展被编译,然后链接。 如前所述,如果内核扩展的默认入口点不是__start ,则必须由-e切换到链接器ld来指定。
注意,内核扩展不应该使用cc构建; 在最后的链接步骤中应使用ld 。
要构建32位和64位版本的内核扩展,请分别使用â????q32和â????q64标志。
在这种情况下,内核扩展入口点不是__start()所以使用â????e开关,找准切入点。 由于在内核扩展中使用了从内核导出的符号,因此可以使用-bI:/usr/lib/kernex.exp来指定该依赖性,该依赖性指向文件。
AIX提供了两个库libsys.a和libcsys.a,内核扩展可以使用它们。 您可以在内核扩展中使用â????lsys和â????lcsys开关链接这两个库。
支持32位和64位
AIX以32位和64位模式运行,并且具有双模式内核扩展。 双模式内核扩展可用于简化32位和64位内核上运行的内核扩展的加载。 双模式内核扩展是一个存档文件,其中包含32位和64位版本的内核扩展作为成员。 当sysconfig或kmod_load调用中指定的路径名是存档时,加载程序将加载对象模式与内核执行模式匹配的第一个存档成员。 在Hello World内核扩展中,您将在32位和64位内核扩展中进行双模内核扩展。
AIX内核扩展的一个复杂之处在于它标识内核扩展的方式。 AIX根据其路径名识别内核扩展。 如果调用内核扩展,请使用其他路径,例如绝对路径(假设您位于/ tmp目录中):
[root@aix1] ./kctrl /tmp/kernext_hello
并再次与:
[root@aix1] ./kctrl ./kernext_hello
内核扩展的这两个实例将被内核视为不同的内核扩展。
高级内核扩展
本节介绍更高级的内核扩展。 内核扩展可以通过在导出文件中列出新系统调用并附加syscall标记,而将新系统调用添加到内核或接管现有系统调用。 加载此类扩展名后,将创建系统调用表的新副本。
您将编写两个与要添加到正在运行的内核的系统调用相关的文件。 一个导出系统调用符号( demo_syscall.exp ),另一个导出系统调用的定义( demo_syscall.c )-一个控制器程序( kctrl.c )控制新系统调用的加载和卸载,一个示例程序( invoke_syscall.c )使用所述新的系统调用,以及一个生成文件构建所有此,如图清单4的下方。
清单4. demo_syscall.exp文件
1 #!/unix
2 demo_syscall syscall
在此文件中,只需导出要定义的系统调用符号,如下面的清单5所示。
清单5.系统调用符号
1 /* A bit advanced kernext */
2
3 #include <stdio.h>
4 #include <errno.h>
5 #include <syslog.h>
6 #include <sys/device.h>
7
8 int demo_syscall_init(int cmd, struct uio *uio)
9 {
10 int iErr = 0;
11
12 bsdlog(LOG_DEBUG | LOG_KERN, "demo_syscall_init:Ã?? command = 0x%x \n",cmd);
13
14 if (cmd == CFG_INIT) {
15
16 bsdlog(LOG_DEBUG | LOG_KERN, " Loading Adv KernExt \n");
17 if(iErr = pincode(demo_syscall_init))
18 return iErr;
19
20 } else if (cmd == CFG_TERM) {
21
22 bsdlog(LOG_DEBUG | LOG_KERN, " UnLoading Adv KernExt \n");
23 if(iErr = unpincode(demo_syscall_init))
24 return iErr;
25
26 } else {
27 bsdlog(LOG_DEBUG | LOG_KERN, " Unknown command to Adv KernExt \n");
28 return -1;
29 }
30
31 return 0;
32 }
33
34 /* Implementation of the demo syscall */
35 demo_syscall(int arg)
36 {
37 return(arg + 25);
38 }
您的新系统调用很简单。 它只是在传递的参数上加上25,然后返回总和(请参见清单6 )。
清单6. kctrl.c清单
1 /* Controller App for KernExt */
2
3 #include <stdio.h>
4 #include <errno.h>
5 #include <string.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <sys/sysconfig.h>
9 #include <sys/device.h>
10
11 int main(int argc, char *argv[])
12 {
13 struct cfg_kmod opt_kmod;
14 struct cfg_load opt_load, query_load;
15 struct stat statbuf;
16 char szKernExt[256], c;
17
18 /* Check if the user has appropriate privileges */
19 if (getuid() != 0) {
20 fprintf(stderr, " Not SuperUser.\n");
21 exit(EACCES);
22 }
23
24 /* Check arguments */
25 if (argc != 2) {
26 printf ("Usage: %s <kernel_extension>\n", argv[0]);
27 exit(EINVAL);
28 }
29
30 strcpy(szKernExt,argv[1]);
31
32 /* Check existence of file */
33 if (stat(szKernExt,&statbuf) != 0) {
34 perror("stat");
35 exit(errno);
36 }
37
38 /* Fill up the cfg_load structure */
39 opt_load.path = szKernExt; /* file name */
40 opt_load.libpath = NULL; /* no library */
41 opt_load.kmid = 0;
42
43 /* Perform various operations on the kernel extension */
44 while(1) {
45
46 fprintf (stderr, "\n Enter choice, (l)oad, (u)nload, (i)nit, (t) erm,
(q)uery or (e)nd\n");
47
48 while((c = getchar()) < 'a' && c > 'z') ; /* discard garbage */
49
50 switch(c) {
51
52 case 'l': /* load a kernel extension */
53
54 /* load kernel extension request */
55 if (sysconfig(SYS_KLOAD,&opt_load,sizeof(struct cfg_load)))
56 perror("sysconfig(SYS_KLOAD)"); /* print error message */
57 else
58 printf("Extension Successfully loaded, kmid is %d\n", opt_load.kmid);
59
60 break;
61
62 case 'i': /* Initialize a KernExt */
63
64 /* Initialize the kernel extension */
65 opt_kmod.kmid = opt_load.kmid;
66 opt_kmod.cmd = CFG_INIT;
67 opt_kmod.mdiptr = NULL;
68 opt_kmod.mdilen = 0;
69 if (sysconfig(SYS_CFGKMOD,&opt_kmod,sizeof(struct cfg_load)) )
70 perror("sysconfig(SYS_CFGKMOD)"); /* print error message */
71 else
72 printf(" Extension Initialized \n");
73
74 break;
75
76 /* Unload kernel extension */
77 case 'u':
78 /* Check if KernExt is loaded */
79 if (opt_load.kmid == 0)
80 printf("kernel Extension not loaded\n");
81 else {
82 if (sysconfig(SYS_KULOAD,&opt_load,sizeof(struct cfg_load)))
83 perror("sysconfig(SYS_KULOAD)");
84 else
85 fprintf(stderr, "KernExt Successfully Unloaded \n");
86 }
87
88 break;
89
90 /* Terminate the kernel extension */
91 case 't':
92
93 /* Check if KernExt is loaded */
94 if (opt_load.kmid == 0)
95 fprintf(stderr, "Extension not loaded\n");
96 else {
97 opt_kmod.kmid = opt_load.kmid;
98 opt_kmod.cmd = CFG_TERM; /* Terminate the kernel extension */
99 opt_kmod.mdiptr = NULL;
100 opt_kmod.mdilen = 0;
101 if (sysconfig(SYS_CFGKMOD,&opt_kmod,sizeof(struct cfg_kmod)))
102 perror("sysconfig(SYS_CFGKMOD)"); /* print error */
103 else
104 fprintf(stderr, " KernExtension Terminated \n");
105 }
106
107 break;
108
109
110 /* query kernel extension existence */
111 case 'q':
112
113 query_load.path = opt_load.path;
114 query_load.libpath = opt_load.libpath ;
115 query_load.kmid = 0;
116
117 if (sysconfig(SYS_QUERYLOAD,&query_load,sizeof(struct cfg_load)))
118 perror("sysconfig(SYS_QUERYLOAD)");
119 else
120 {
121 if(query_load.kmid > 0)
122 fprintf(stderr, " Extension is loaded, with kmid %d \n",
query_load.kmid);
123 else
124 fprintf(stderr, " Extension is not loaded \n");
125 }
126 break;
127
128 case 'e':
129 exit(0);
130
131
132 default:
133 fprintf(stderr, "Incorrect option \n");
134 break;
135 }
136 getchar();
137 }
138
return 0;
140 }
清单7是处理内核扩展加载和卸载的控制器程序。
清单7. invoke_syscall.c的清单
1 /* Call the implemented Demo system call */
2 #include <stdio.h>
3
4 int main()
5 {
6 int iVal = 0;
7
8 fprintf(stderr, " Invoking demo syscall \n");
9
10 if ( (iVal = demo_syscall(99)) < 0)
11 {
12 perror("demo_syscall error");
13 exit(1);
14 }
15
16 fprintf(stderr, " Got Value - %d\n",iVal);
17
18
19 return 0;
20 }
这只是使用新系统调用的示例程序。
下面的清单8是用于生成高级内核扩展的所有程序的Makefile。
清单8.生成高级内核扩展的所有程序的Makefile
1 all: demo_syscall invoke_syscall kctrl
2
3 kctrl: kctrl.c
4 cc -o kctrl kctrl.c
5
6 invoke_syscall: invoke_syscall.c
7 cc -o invoke_syscall -bI:demo_syscall.exp invoke_syscall.c
8
9 demo_syscall: demo_syscall.c
10 cc -q32 -o demo_syscall32.o -qlist -qsource -c demo_syscall.c
11 mv demo_syscall.lst demo_syscall32.lst
12 ld -b32 -o demo_syscall32 demo_syscall32.o -e demo_syscall_init
-bI:/usr/lib/kernex.exp -bE:demo_syscall.exp -lsys -l csys
13 cc -q64 -o demo_syscall64.o -qlist -qsource -c demo_syscall.c
14 mv demo_syscall.lst demo_syscall64.lst
15 ld -b64 -o demo_syscall64 demo_syscall64.o -e demo_syscall_init
-bI:/usr/lib/kernex.exp -bE:demo_syscall.exp -lsys -l csys
16 rm -f demo_syscall
17 ar -X32_64 -r -v demo_syscall demo_syscall32 demo_syscall64
18
19 clean:
20 rm -f *.o invoke_syscall demo_syscall demo_syscall32 demo_syscall64 kctrl
demo_syscall64.lst demo_syscall32.lst 2> /dev/null
翻译自: https://www.ibm.com/developerworks/aix/library/au-kernelext.html