内核中的UDP socket流程(2)——API “sys_socket”
作者:gfree.wind@gmail.com
前面已经列出了UDP常用的4个API,那么下面从第一个API “sys_socket”开始
1272 SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) 1273 { 1274 int retval; 1275 struct socket *sock; 1276 int flags; 1277 1278 /* Check the SOCK_* constants for consistency. */ 1279 BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC); 1280 BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK); 1281 BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK); 1282 BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK); 1283 1284 flags = type & ~SOCK_TYPE_MASK; 1285 if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1286 return -EINVAL; 1287 type &= SOCK_TYPE_MASK; 1288 1289 if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1290 flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1291 1292 retval = sock_create(family, type, protocol, &sock); 1293 if (retval 0) 1294 goto out; 1295 1296 retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); 1297 if (retval 0) 1298 goto out_release; 1299 1300 out: 1301 /* It may be already another descriptor 8) Not kernel problem. */ 1302 return retval; 1303 1304 out_release: 1305 sock_release(sock); 1306 return retval; 1307 }
|
1272行:使用宏
SYSCALL_DEFINE3定义了内核export出来的API “sys_socket”,参数是int family, int type, 和int protocol。
1279~1282行:对于这些常量作出编译期间的检查。
1284~1286行:在linux2.6.27以前的版本,参数int type只能取真正的socket type的值,即下面的
enum sock_type { SOCK_STREAM = 1, SOCK_DGRAM = 2, SOCK_RAW = 3, SOCK_RDM = 4, SOCK_SEQPACKET = 5, SOCK_DCCP = 6, SOCK_PACKET = 10, };
|
但是在Linux 2.6.27版本以后,type有了第二个用途,它可以或上下面的两个数,来指定socket的行为。
#define SOCK_CLOEXEC O_CLOEXEC #ifndef SOCK_NONBLOCK #define SOCK_NONBLOCK O_NONBLOCK #endif
|
所以,1284行到1286行,是为了检测是否type是否只set了上面两个位。如果不是的话,即为非法的type,返回错误EINVAL。
1287行:获得真正的type值
1289~1290行:如果socket的NOBLOCK标志位不等于普通的文件描述符标志的NOBLOCK标志,且该socket设置了SOCK_NONBLOCK,那么就取消这个SOCK_NONBLOCK标志位,并设置上O_NONBLOCK标志位。
在sock_create之后,我们获得了一个socket,然后调用sock_map_fd,将其映射为文件描述符,并将这个描述符返回给用户。
今天又晚了。。。正在看
sock_create的代码,明天继续吧。