With the introduction of AIX® Version 5.3, coupled with the rapid improvements in Power architecture and its growth in the *nix market, worldwide developers are becoming more interested in AIX. This article helps you get started on developing your own kernel extensions on AIX.
The AIX kernel provides the interface to dynamically extend its functions by using kernel extensions. Kernel extensions are routines added to the kernel to extend its functions. Kernel extensions are an important part of the AIX kernel architecture, and they are similar to dynamically loadable modules available on other platforms, such as Linux®, that add function to the running kernel without the need of a machine reboot.
Kernel extensions run in the kernel protection domain. You might need a kernel extension if, for example, you need to create your own system call, kernel processes, or file system. A kernel extension runs in the same mode as the kernel. If the kernel is running in 64-bit mode, the extension must also be able to run in that mode.
This article is for anyone who wants to write their own kernel extension on AIX. Only a basic understanding of UNIX® programming is required.
The term kernext is occasionally used as an abbreviation for kernel extension, especially in the code.
The routines added to extend an AIX kernel might fall into the following categories:
- System calls
- Virtual file systems
- Kernel extension and device driver management kernel services
- Device drivers
Regardless of the category the routine falls into, they are called kernel extensions.
The life cycle of a kernel extension has the following phases, including:
- Loading -- This phase loads the kernel extension in kernel memory.
- Executing -- This phase starts the execution of the kernel extension and calls its entry point. This is the initialization.
- Communicating -- This phase communicates with the kernel extension. Now the kernel extension is doing its job.
- Terminating -- This phase terminates the kernel extension.
- Unloading -- This unloads the kernel extension from memory.
The sysconfig() system call is used to control these phases. sysconfig( needs super-user privileges, and it is the primary application programming interface (API) for managing kernel extensions. Its declaration is:
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() takes a command (cmd) parameter that selects the action the caller wants. Some common actions are listed in Table 1 below. For the exhaustive list, see /usr/include/sys/sysconfig.h.
Table 1. Common actions
| Action | Description |
|---|---|
| *) SYS_KLOAD | Loads a kernel extension object file in kernel memory. |
| *) SYS_SINGLELOAD | Loads a kernel extension object file only if it is not already loaded. |
| *) SYS_QUERYLOAD | Determines if a specified kernel object file is loaded. |
| *) SYS_KULOAD | Unloads a previously loaded kernel object file. |
| *) SYS_CFGKMOD | Calls the specified module at its module entry point for configuration purposes. |
You can use your own custom command code, provided it is handled properly. You can also use the strload command to load, or unload, a kernel extension. Generally, you have to write your own code to load your kernel extension.
Let's have a look at some of the important structures involved:
Struct cfg_load |
This structure is passed to
sysconfig() when you load, or unload, a kernel extension. This structure is defined in /usr/include/sys/sysconfig.h as:
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) */
}; |
The structure members of struct cfg_load are:
path-- This command specifies the pathname of the object file of your kernel extension module.libpath-- This command is the path to be searched for the kernel extension object file. If this field is null, the path field is used instead.Kmid-- This command contains the kernel module ID. Depending on the option, you pass tosysconfig(). It is either filled bysysconfig(), or it has to be passed tosysconfig( ).
The Struct cfg_kmod structure is passed to sysconfig( ) when you invoke the module entry point. Struct cfg_kmod is defined in /usr/include/sys/sysconfig.h as:
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 */
}; |
The structure members of
cfg_kmod are:
kmid-- This command specifies the kernel extension module ID, which is returned after a module is loaded.cmd-- This command specifies the command for the module. This can be a user-defined value, or can be taken from <sys/device.h>, as you have done in the example below.mdiptr-- This command is used to pass data to the kernel extension.mdilen-- This command contains the length of the data passed inmdiptr.
Now let's move on to something tangible.
A Hello World kernel extension
You should now be able to start writing a simple "Hello World" kernel extension. You'll write two programs:
- A controller application, which controls and configures your kernel extension
- The actual Hello World kernel extension
To compile the sample code for a Hello World kernel extension, just type make in the directory where you've copied the source code. For obvious security reasons, only the root user can load, or unload, kernel extensions. Since the loaded code runs in kernel mode, it has complete access to anything on the system. Thus, even a setuid program, owned by root, is not enough to load a kernel extension -- you must be logged in as root. See Listing 1 below.
Listing 1. The controller application: 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 }
|
Now you need to define variables of type, in particular, struct cfg_kmod and struct cfg_load.
struct cfg_kmod opt_kmod; struct cfg_load opt_load, query_load; |
Initially, to load the kernel extension, you need to call sysconfig with the SYS_KLOAD command parameter. You pass opt_load and
sizeof(struct cfg_load) as:
sysconfig(SYS_KLOAD,&opt_load,sizeof(struct cfg_load)) |
After a successful call to
sysconfig, you get the kmid, which gets printed on the screen.You fill up the cfg_load structure with the path for the kernel extension:
opt_load.path = szKernExt; |
You set the libpath to NULL because, in this case, you are not depending on any nonsystem defined library:
opt_load.libpath = NULL; |
You initialize the kmid field to zero:
opt_load.kmid = 0; |
Execute the code, as shown below:
[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 |
You can view the list of the loaded kernel extension on your system using the genkex command:
[root@aix1] genkex Text address Size File 2ec3000 2d8 ./kernext_hello <Snip> |
Initializing the kernel extension
After loading your kernel extension, you call sysconfig( ) to invoke its entry point using the CFG_INIT command.
The controller application uses the sysconfig() routine. You fill in the struct cfg_kmod opt_kmod, as shown below:
opt_kmod.kmid = opt_load.kmid; opt_kmod.cmd = CFG_INIT; opt_kmod.mdiptr = NULL; opt_kmod.mdilen = 0; |
You'll fill in the kmid field with the identifier of the kernel extension, which you got from your previous call to sysconfig( ).
The CFG_INIT command invokes the entry point for the kernel extension. For now, you aren't passing any arguments to the kernel extension, hence, mdiptr is NULL. Mdilen contains the length of mdiptr.
In the sample kernel extension, we've added routines that print the output in the syslog file. Check the syslog output on your system; it should have output similar to the one below:
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 |
You can query whether your extension is loaded or not using struct cfg_load. You can use the query_load variable to do this.
Now fill in the path and libpath values from the opt_load variable and call sysconfig with the command SYS_QUERYLOAD, as shown below:
query_load.path = opt_load.path; query_load.libpath = opt_load.libpath ; query_load.kmid = 0; |
If the kernel extension is loaded, the kmid field has the kmid of the kernel extension, which is always greater than zero. As shown below, you get the kmid of your kernel extension:
[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 |
Terminating the kernel extension
To terminate the kernel extension, call sysconfig() with the CFG_TERM command embedded in struct cfg_kmod. Then fill in the opt_kmod variable with the values, as shown below:
opt_kmod.kmid = opt_load.kmid; opt_kmod.cmd = CFG_TERM; opt_kmod.mdiptr = NULL; opt_kmod.mdilen = 0; |
Now you have the kmid, and you can fill in the command as CFG_TERM, as shown below:
[root@aix1] ./kctrl ./kernext_hello Enter choice, (l)oad, (u)nload, (i)nit, (t)erm, (q)uery or (e)nd t KernExtension Terminated |
In the syslog output, you would see the lines below:
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 |
Unloading the kernel extension
To unload your kernel extension, you call sysconfig with the SYS_KULOAD parameter and pass struct cfg_load, which has the path and kmid field filled in, as shown below:
sysconfig(SYS_KULOAD,&opt_load,sizeof(struct cfg_load) |
To unload the kernel extension, use the option "u" and select Enter, as follows:
[root@aix1] ./kctrl ./kernext_hello Enter choice, (l)oad, (u)nload, (i)nit, (t)erm, (q)uery or (e)nd u KernExt Successfully Unloaded |
Be careful while using sysconfig(); incorrect values for kmid could crash the system (see Listing 2).
Listing 2. Hello World kernel extension: 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 } |
A kernel extension has no main() routine; instead it has an entry point, which is invoked by the controller application when the CFG_INIT command is issued using SYS_CFGKMOD with sysconfig().
In the kernel extension sample, you have only one function, the kernel extension entry point, which is hello_init(). The entry point has two arguments and an integer, which is the command parameter passed from sysconfig(), which is embedded in struct cfg_kmod.
The other parameter is struct uio, which is used to pass data to the kernel extension. In the Hello World kernext, you are not using struct uio, as shown in the previous section.
By default, the name of the entry point needs to be __start( ). If you specify a different name, as in this case, you need to specify that while building your kernel extension.
The Hello World kernel extension acknowledges receipt of the commands, and it prints them out. It uses bdslog() to print. The first argument to bsdlog is the priority. You are using two flags for the priority:
- LOG_DEBUG, which tells syslog that this is a debug message
- LOG_KERN, which tells syslog that this message is from the kernel
To get the log message, make sure that syslogd is configured.
For example, in /etc/syslog.conf, you can add something like:
*.debug /tmp/syslog.out rotate size 100k files 4 |
Then ps âaef | grep syslog, and give it kill âHUP.
The build process in Listing 3 below is the Makefile for the Hello World kernel extension.
Listing 3. Makefile for the Hello World kernel extension
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 |
In the Makefile, you have two targets: the controller application and the Hello World kernel extension.
The command for the controller application is quite straightforward, where you specify the object file using the -o option:
4 cc -o kctrl kctrl.c |
Kernel extensions are compiled, and then linked. As mentioned, if the default entry point of a kernel extension is other than __start, it has to be specified by -e switched to linker ld.
Note that kernel extensions should not be built with cc; ld should be used in the final link step.
To build a 32-bit and a 64-bit version of the kernel extension, use the âq32 and âq64 flags, respectively.
In this case, the kernel extension entry point is not __start(), so use the âe switch to identify the entry point.
Since you use symbols exported from the kernel in your kernel extension, you specify that dependency using -bI:/usr/lib/kernex.exp, which points to the file.
AIX provides two libraries, libsys.a and libcsys.a, that can be used by a kernel extension. You can link these two libraries using âlsys and âlcsys switches in your kernel extension.
AIX runs in 32- and 64-bit modes, and it has dual-mode kernel extensions. Dual-mode kernel extensions can be used to simplify the loading of kernel extensions that run on both the 32- and 64-bit kernels.
A dual-mode kernel extension is an archive file that contains both the 32- and 64-bit versions of the kernel extension as members.
When the pathname specified in the sysconfig or kmod_load call is an archive, the loader loads the first archive member whose
object mode matches the kernel's execution mode.
In the Hello World kernel extension, you make a dual-mode kernel extension out of the 32- and 64-bit kernel extension.
One intricacy of an AIX kernel extension is in the way it identifies kernel extensions. AIX recognizes the kernel extensions based on their path names. If you invoke your kernel extension, use different paths, such as an absolute path (assume you are in the /tmp directory):
[root@aix1] ./kctrl /tmp/kernext_hello |
And again with:
[root@aix1] ./kctrl ./kernext_hello |
Both of these instances of kernel extensions will be treated as different kernel extensions by the kernel.
This section looks at a bit more advanced kernel extension.
Kernel extensions can add new system calls to the kernel, or take over existing ones, simply by listing the new system calls in an export file, with the syscall tag attached. When such an extension is loaded, a new copy of the system call table is created.
You'll write two files related to the system call you are going to add to the running kernel. One exports the syscall symbol (demo_syscall.exp) and the other has the definition of the system call (demo_syscall.c) -- one controller program (kctrl.c) to control loading and unloading of the new system call, one sample program (invoke_syscall.c) using the new system call, and one Makefile to build all this, as shown in Listing 4 below.
Listing 4. The demo_syscall.exp file
1 #!/unix
2 demo_syscall syscall |
In this file, you just export the system call symbol that you are defining, as shown in Listing 5 below.
Listing 5. System call symbol
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 } |
Your new system call is trivial. It simply adds 25 to the argument passed, and it returns the sum (see Listing 6).
Listing 6. Listing of 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 }
|
Listing 7 is the controller program that handles loading and unloading of the kernel extension.
Listing 7. Listing of 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 }
|
This is just a sample program using the new system call.
Listing 8 below is the Makefile to build all the programs of your advanced kernel extension.
Listing 8. Makefile to build all the programs of your advanced kernel extension
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
|
Learn
- AIX 5L Version 5.3 Kernel Extensions and Device Support Programming Concepts: Learn all about kernel programming and the kernel environment for the AIX operating system.
- AIX 5L Version 5.3 Technical Reference: Kernel and Subsystems, Volume 1: Provides system programmers with complete detailed information about kernel services, device driver operations, and file system operations for the AIX operating system.
- AIX 5.L Version 5.3 Technical Reference: Kernel and Subsystems, Volume 2: Provides system programmers with complete detailed information about the configuration subsystem, the communications subsystem, the LFT subsystem, printer subsystems, the SCSI subsystem, Integrated Device Electronics, the SSA subsystem, and the serial DASD subsystem for the AIX operating system.
- OpenAFS : OpenAFS has an AIX port, and it contains a good implementation of AIX filesystem.
- AIX and UNIX: Want more? The developerWorks AIX and UNIX zone hosts hundreds of informative articles and introductory, intermediate, and advanced tutorials.
- New to AIX and UNIX: Visit the New to AIX and UNIX page to learn more about AIX and UNIX.
- developerWorks
technical events and webcasts: Stay current with developerWorks technical events and webcasts.
- AIX 5L Wiki: A collaborative environment for technical information related to AIX.
- Podcasts: Tune in and catch up with IBM technical experts.
Get products and technologies
- IBM trial software: Build your next development project with software for download directly from developerWorks.
Discuss
-
Participate in the AIX and UNIX forums:
- AIX 5L -- technical
- AIX for Developers Forum
- Cluster Systems Management
- IBM Support Assistant
- Performance Tools -- technical
- Virtualization -- technical
- More AIX and UNIX forums
- Participate in the developerWorks
blogs and get involved in the developerWorks community.

Sandesh Chopdekar works as a Staff Software Engineer for IBM, specializing in distributed filesystems and networking. Prior to joining IBM, Sandesh worked for a subsidiary of Citicorp. He holds a BS degree in chemistry from Mumbai University.
Avinesh Kumar works as a System Software Engineer for the Andrew File System Team at the IBM Software Labs in Pune, India. He works with kernel- and user-level debugging of dumps and crashes, as well as reported bugs on the Linux, AIX, and Solaris platforms. Avinesh has an MCA from the Department of Computer Science at the University of Pune. He is a Linux enthusiast who spends his spare time exploring the Linux kernel on his Fedora Core 6 box.



