Hi all
these days I'm trying to add 4 new func() to kernel,I use RedHat 8 (Kernel 2.4.18-14) and here is what I did:
Add new syscalls,in /usr/src/linux-2.4.18-14/arch/i386/kernel/entry.S added the names of new sys_calls:
Code:
.long SYMBOL_NAME(sys_evntopen)
.long SYMBOL_NAME(sys_evntclose)
.long SYMBOL_NAME(sys_evntwait)
.long SYMBOL_NAME(sys_evntsig)
Then in /usr/src/linux-2.4.18-14/include/asm-i386/unistd.h added sys_calls Number:
Code:
#define __NR_evntopen 259
#define __NR_evntclose 260
#define __NR_evntwait 261
#define __NR_evntsig 262
of course in this version of kernel, the max number of syscall defined in
/usr/src/linux-2.4.18-14/include/linux/sys.h is 256,so, I edit it as:
Code:
#define NR_syscalls 270
Then is code:
In/usr/src/linux-2.4.18-14/include/linux/wait.h ,added:
Code:
struct evnt_queue /*define a struct*/
{
struct evnt_queue *next_event;
wait_queue_head_t waitq;
int eid;
};
extern struct evnt_queue *eq; /*should it like this be ? the *eq is used below*/
In /usr/src/linux-2.4.18-14/init/main.c added init func():
Code:
#include </linux/wait.h> /*added #include files*/
#include </linux/mm.h>
#include </linux/slab.h>
......
......
struct evnt_queue *eq; /*defined in wait.h*/
static void __init event_init(void) /*init, alloc mem and set the struct-members*/
{
eq=(struct evnt_queue *)kmalloc(
sizeof(struct evnt_queue), GFP_KERNEL);
eq->next_event=NULL;
eq->eid=0;
init_waitqueue_head(&(eq->waitq));
}
......
......
asmlinkage void __init start_kernel(void)
/*this func() is already existed, added the init func() above in the last line*/
{
......
event_init(); /*last line*/
}
In /usr/src/linux2.4.18-14/kernel/sys.c , added 4 new func():
Code:
#include </linux/wait.h> /*added include*/
#include </linux/mm.h>
#include </linux/slab.h>
......
......
asmlinkage int sys_evntopen(int eid) /*open an event*/
{
int newid=-1;
struct evnt_queue *temp;
printk("here event opens");
if (eq==NULL)
{
eq=(struct evnt_queue *)kmalloc(
sizeof(struct evnt_queue), GFP_KERNEL);
eq->next_event=NULL;
eq->eid=0;
init_waitqueue_head(&(eq->waitq));
}
temp=eq->next_event;
if (eid>0)
{
while ((temp!=NULL)&&(temp->eid!=eid))
{
temp=temp->next_event;
}
if ((temp!=NULL)&&(temp->eid==eid)) newid=eid;
}
else if (eid==0)
{
while (temp!=NULL)
{
if (newid<temp->eid) newid=temp->eid;
temp=temp->next_event;
}
newid++;
if (newid<1) newid=1;
temp=(struct evnt_queue *)kmalloc(
sizeof(struct evnt_queue), GFP_KERNEL);
if (temp==NULL) newid=-1;
else
{
temp->eid=newid;
temp->next_event=eq->next_event;
eq->next_event=temp;
init_waitqueue_head(&(temp->waitq));
}
}
return(newid);
}
asmlinkage int sys_evntclose(int eid) /*close an event*/
{
int result=-1;
struct evnt_queue *prev, *temp;
printk("here event closes"); /*the error when excecuting comes from here? Why is a NULL pointer ?*/
prev=eq;
temp=prev->next_event;
while ((temp!=NULL)&&(temp->eid!=eid))
{
prev=temp;
temp=prev->next_event;
}
if ((temp!=NULL)&&(waitqueue_active(&(temp->waitq))))
wake_up_interruptible(&(temp->waitq));
if (temp!=NULL)
{
result=0;
prev->next_event=temp->next_event;
kfree(temp);
}
return(result);
}
asmlinkage int sys_evntwait(int eid) /*event wait*/
{
int result=-1;
struct evnt_queue *temp;
printk("here event waits");
temp=eq->next_event;
while ((temp!=NULL)&&(temp->eid!=eid))
{
temp=temp->next_event;
}
if (temp!=NULL)
{
result=0;
interruptible_sleep_on(&(temp->waitq));
}
return(result);
}
asmlinkage int sys_evntsig(int eid) /*event signaling*/
{
int result=-1;
struct evnt_queue *temp;
printk("event sig");
temp=eq->next_event;
while ((temp!=NULL)&&(temp->eid!=eid))
{
temp=temp->next_event;
}
if (temp!=NULL)
{
result=0;
wake_up_interruptible(&(temp->waitq));
}
return(result);
}
well, re-compile the kernel, and no error appeared, ......
edit a tester named test.c:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <linux/unistd.h>
#include <linux/wait.h>
_syscall1(int, evntopen, int, eid);
_syscall1(int, evntclose, int, eid);
_syscall1(int, evntwait, int, eid);
_syscall1(int, evntsig, int, eid);
void *task_wait(void *eid) /* eventwait */
{
printf("event %d waiting\n", eid);
evntwait((int)eid);
printf("event %d waked up\n", eid);
}
void *task_signal(void *eid) /* eventsig */
{
printf("event %d signaling\n", eid);
evntsig((int)eid);
}
int main(int arg, char ** argv)
{
int i, k, n;
int eids[10];
pthread_t tasks[10];
n=3; /* open 3 threads */
for (i=0; i<n; i++)
{
eids[i]=evntopen(0); /* open events */
if (eids[i]>0) printf("event %d opened\n", eids[i]);
else printf("event #%d could not open\n", i);
}
for (i=0; i<n; i++)
{
/* creat threads */
pthread_create(&tasks[i], NULL, task_wait, (void *)eids[i]);
sleep(2);
}
for (i=n-1; i>=0; i--)
{
pthread_create(&tasks[i], NULL, task_signal, (void *)eids[i]);
sleep(2);
}
for (i=0; i<n; i++)
{
k=evntclose(eids[i]); /* test eventclose */
if (k==0) printf("event %d closed\n", eids[i]);
else printf("event %d could not close\n", eids[i]);
}
for (i=0; i<n; i++)
{
pthread_join(tasks[i], NULL);
}
return(0);
}
compile and excecute:
#cc -o test test.c -lpthread
#./test
error: Segmentation fault
in system log:
Code:
Feb 9 11:30:54 localhost kernel: here event closes<1>Unable to handle
kernel NULL pointer dereference at virtual address 00000000
Feb 9 11:30:54 localhost kernel: printing eip:
Feb 9 11:30:54 localhost kernel: c0127de2
Feb 9 11:30:54 localhost kernel: *pde = 00000000
Feb 9 11:30:54 localhost kernel: Oops: 0000
Feb 9 11:30:54 localhost kernel: autofs pcnet32 mii ipt_REJECT
iptable_filter ip_tables mousedev keybdev input
Feb 9 11:30:54 localhost kernel: CPU: 0
Feb 9 11:30:54 localhost kernel: EIP: 0010:[<c0127de2>] Not tainted
Feb 9 11:30:54 localhost kernel: EFLAGS: 00010286
Feb 9 11:30:54 localhost kernel:
Feb 9 11:30:54 localhost kernel: EIP is at sys_evntclose [kernel] 0x22
(2.4.18-2418-14-new-2)
Feb 9 11:30:54 localhost kernel: eax: 00000011 ebx: ca152000 ecx:
00000001 edx: 00000082
Feb 9 11:30:54 localhost kernel: esi: 00000000 edi: 00000000 ebp:
ffffffff esp: ca153fac
Feb 9 11:30:54 localhost kernel: ds: 0018 es: 0018 ss: 0018
Feb 9 11:30:54 localhost kernel: Process test_proj8 (pid: 849,
stackpage=ca153000)
Feb 9 11:30:54 localhost kernel: Stack: c02510cd ca152000 40012020 bffffb54
bffffa78 c010910f 00000000 421261e8
Feb 9 11:30:54 localhost kernel: 4212aa68 40012020 bffffb54 bffffa78
000000f4 0000002b 0000002b 000000f4
Feb 9 11:30:54 localhost kernel: 08048499 00000023 00010282 bffffa70
0000002b
Feb 9 11:30:54 localhost kernel: Call Trace: [<c010910f>] system_call
[kernel] 0x33 (0xca153fc0))
Feb 9 11:30:54 localhost kernel:
Feb 9 11:30:54 localhost kernel:
Feb 9 11:30:54 localhost kernel: Code: 8b 1e 85 db 74 2f 39 7b 0c 74 10 8d
76 00 89 de 8b 1b 85 db
why only evntclose info ?......excecuted evntclose only ?My C is not good and just started Kernel learning......
thanks for any help and info, thanks!!