http://www.eoeandroid.com/thread-4668-1-1.html
http://blog.chinaunix.net/uid-9078996-id-2010323.html
http://blog.csdn.net/andyhuabing/article/details/7183369
1、Syscall stub:
每个系统调用函数都由一个小的汇编代码段实现(称为”syscall stub”),这是由tools/gensyscalls.py工具自动生成的,它从SYSCALL.TXT中取得输入参数。SYSCALLS.TXT包含了一份要生成的系统调用块列表,和相应的系统调用数字标识符(ARM和X86不一样),以及它的签署。
如果你要修改这个文件,你可能要使用tools/checksyscalls.py工具,检查它里面是否包含官方linux核心头文件,如果有不合法的syscall ids,它会报告错误。
有时,C库函数其实就是一个包装,它内部调用相应的syscall名称,例如,exit函数由C库提供,它调用了_exit()这个syscall stub.
详细内容请参考SYSCALLS.TXT文件。
2、比如要增加消息队列的函数:
(1). 修改 SYSCALL.TXT
增加:
long ipc(unsigned int call, int first, unsigned long second, unsigned long third, void __user *ptr, long fifth) 117
(2). 执行 tools/gensyscalls.py
(3). 以下内容会由 tools/gensyscalls.py 自动产生:
bionic/libc/arch-mips/syscalls.mk
----------------------------------------------------------------------------------------------------------------------------
syscall_src += arch-mips/syscalls/ipc.S
----------------------------------------------------------------------------------------------------------------------------
bionic/libc/include/sys/linux-syscalls.h
----------------------------------------------------------------------------------------------------------------------------
#define _NR_ipc (_NR_SYSCALL_BASE + 117)
----------------------------------------------------------------------------------------------------------------------------
bionic/libc/include/sys/linux-unistd.h
----------------------------------------------------------------------------------------------------------------------------
int ipc (unsigned int call, int first, int second, int third, void* ptr, long fifth);
----------------------------------------------------------------------------------------------------------------------------
(4). 手动编写
bionic/libc/Android.mk
----------------------------------------------------------------------------------------------------------------------------
ifeq ($(TARGET_ARCH),mips)
libc_common_src_files += \
arch-mips/bionic/sys_ipc.c \
----------------------------------------------------------------------------------------------------------------------------
bionic/libc/arch-mips/bionic/sys_ipc.c
----------------------------------------------------------------------------------------------------------------------------
#include <stdarg.h>
#include <sys/msg.h>
extern int ipc (unsigned int call, int first, int second, int third, void* ptr, long fifth);
int semget (key_t key, int nsems, int semflg)
{
return ipc(SEMGET, key, nsems, semflg, (void*)NULL, (long)NULL);
}
int semop (int semid, struct sembuf* sops, size_t nsops)
{
return ipc(SEMOP, semid, (int)nsops, 0, sops, (long)NULL);
}
void* shmat (int shmid, const void* shmaddr, int shmflg)
{
int rval;
unsigned long raddr;
rval = ipc(SHMAT, shmid, shmflg, (int)&raddr, (void*)shmaddr, (long)NULL);
if (rval < 0)
return (char *)rval;
return (char *)raddr;
}
int shmctl (int shmid, int cmd, struct shmid_ds* buf)
{
return ipc(SHMCTL, shmid, cmd, 0, buf, (long)NULL);
}
int shmget (key_t key, size_t size, int shmflg)
{
return ipc(SHMGET, key, size, shmflg, (void*)NULL, (long)NULL);
}
int msgctl (int msqid, int cmd, struct msqid_ds *buf)
{
return ipc(MSGCTL, msqid, cmd, 0, buf, (long)NULL);
}
int shmdt (const void* shmaddr)
{
return ipc(SHMDT, 0, 0, 0, (void*)shmaddr, (long)NULL);
}
int msgget (key_t key, int msgflg)
{
return ipc(MSGGET, key, msgflg, 0, NULL, (long)NULL);
}
ssize_t msgrcv (int msqid, void *msgp, size_t msgsz, long int msgtyp, int msgflg)
{
struct ipc_kludge tmp;
tmp.msgp = msgp;
tmp.msgtyp = msgtyp;
return ipc(MSGRCV, msqid, msgsz, msgflg, &tmp, (long)NULL);
}
int msgsnd (int msqid, const void* msgp, size_t msgsz, int msgflg)
{
return ipc(MSGSND, msqid, msgsz, msgflg, (void*)msgp, (long)NULL);
}
bionic/libc/arch-mips/syscalls/ipc.S
----------------------------------------------------------------------------------------------------------------------------
/* autogenerated by gensyscalls.py */
#include <sys/linux-syscalls.h>
.text
.globl ipc
.align 4
.ent ipc
ipc:
.set noreorder
.cpload $t9
li $v0, __NR_ipc
syscall
bnez $a3, 1f
move $a0, $v0
j $ra
nop
1:
la $t9,__set_errno
j $t9
nop
.set reorder
.end ipc
----------------------------------------------------------------------------------------------------------------------------
bionic/libc/include/sys/msg.h
----------------------------------------------------------------------------------------------------------------------------
#ifndef _SYS_MSG_H
#define _SYS_MSG_H
#include <features.h>
#define __need_size_t
#include <stddef.h>
/* Get common definition of System V style IPC. */
#include <sys/ipc.h>
/* Get system dependent definition of `struct msqid_ds' and more. */
#include <msq.h>
/* Define types required by the standard. */
#define __need_time_t
#include <time.h>
#ifndef __pid_t_defined
typedef __pid_t pid_t;
# define __pid_t_defined
#endif
#ifndef __ssize_t_defined
typedef __ssize_t ssize_t;
# define __ssize_t_defined
#endif
#define SEMOP 1
#define SEMGET 2
#define SEMCTL 3
#define SEMTIMEDOP 4
#define MSGSND 11
#define MSGRCV 12
#define MSGGET 13
#define MSGCTL 14
#define SHMAT 21
#define SHMDT 22
#define SHMGET 23
#define SHMCTL 24
/* The following System V style IPC functions implement a message queue
system. The definition is found in XPG2. */
#ifdef __USE_GNU
/* Template for struct to be used as argument for `msgsnd' and `msgrcv'. */
struct msgbuf
{
long int mtype; /* type of received/sent message */
char mtext[1]; /* text of the message */
};
#endif
struct ipc_kludge {
struct msgbuf __user *msgp;
long msgtyp;
};
__BEGIN_DECLS
/* Message queue control operation. */
extern int msgctl (int __msqid, int __cmd, struct msqid_ds *__buf) ;
/* Get messages queue. */
extern int msgget (key_t __key, int __msgflg) ;
/* Receive message from message queue.
This function is a cancellation point and therefore not marked with
__THROW. */
extern ssize_t msgrcv (int __msqid, void *__msgp, size_t __msgsz, long int __msgtyp, int __msgflg);
/* Send message to message queue.
This function is a cancellation point and therefore not marked with
__THROW. */
extern int msgsnd (int __msqid, __const void *__msgp, size_t __msgsz, int __msgflg);
__END_DECLS
#endif /* sys/msg.h */
----------------------------------------------------------------------------------------------------------------------------
Create bionic/libc/include/msq.h
#ifndef _SYS_MSG_H
#error "Never use <msq.h> directly; include <sys/msg.h> instead."
#endif
#include <sys/types.h>
/* Define options for message queue functions. */
#define MSG_NOERROR 010000 /* no error if message is too big */
/* Types used in the structure definition. */
typedef unsigned short int msgqnum_t;
typedef unsigned short int msglen_t;
/* Structure of record for one message inside the kernel.
The type `struct __msg' is opaque. */
struct msqid_ds
{
struct ipc_perm msg_perm; /* structure describing operation permission */
__time_t msg_stime; /* time of last msgsnd command */
__time_t msg_rtime; /* time of last msgrcv command */
__time_t msg_ctime; /* time of last change */
msgqnum_t msg_qnum; /* number of messages currently on queue */
msglen_t msg_qbytes; /* max number of bytes allowed on queue */
__pid_t msg_lspid; /* pid of last msgsnd() */
__pid_t msg_lrpid; /* pid of last msgrcv() */
};