aix 内核编译

    技术2024-06-04  83

    随着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和libcs​​ys.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

    Processed: 0.019, SQL: 9