1.描述符的概念
通过调用socket函数,可以获得一个socket描述符,这个描述符具体其他Unix描述符的所有特性:可以用这个描述符调用read和write,调用fork后,父进程和子进程可以共享它;
一个描述符是进程的进程表表项的一个数组的下标,这个数组项指向一个打开文件表的结构;
进程可以通过描述符访问插口上的网络连接;
2. 系统调用
进程同内核的交互是通过一组已经定义好的函数来进行的,这些函数就称为系统调用;
在BSD内核中,每个系统调用都对应一个编号,当进程执行一个系统调用时,标识系统调用的整数作为参数被传递给内核函数syscall,根据编号syscall在表中找到请求的系统调用的sysent结构;
struct sysent
{
int sys_narg; /* 参数个数 */
int (*sy_call) (); /* 要执行的函数 */
};
struct sysent sysent[] = {
/* ... */
{3, recvmsg}, /* 27 = recvmsg */
{3, sendmsg}, /* 28 = sendmsg */
{6, recvfrom}, /* 29 = recvfrom */
/* ... */
};
syscall将参数从调用进程复制到内核中,并分配一个数组来保存系统调用的结果,当系统调用执行完后,syscall将结果返回给进程;
例如:
socket系统调用的原型是:
int socket(int family, int type, int protocol);
实现socket系统调用的内核函数的原型是:
socket(struct proc *p, struct socket_args *uap, int *retval);
指针p指向调用系统调用的进程表项;
retval是用来保存系统调用返回结果的数组;