天天看點

核心中的UDP socket流程(2)——API “sys_socket”核心中的UDP socket流程(2)——API “sys_socket”

作者:[email protected]

前面已經列出了UDP常用的4個API,那麼下面從第一個API “sys_socket”開始

<code>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 &amp; SOCK_TYPE_MASK); 1282     BUILD_BUG_ON(SOCK_NONBLOCK &amp; SOCK_TYPE_MASK); 1283 1284     flags = type &amp; ~SOCK_TYPE_MASK; 1285     if (flags &amp; ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1286         return -EINVAL; 1287     type &amp;= SOCK_TYPE_MASK; 1288 1289     if (SOCK_NONBLOCK != O_NONBLOCK &amp;&amp; (flags &amp; SOCK_NONBLOCK)) 1290         flags = (flags &amp; ~SOCK_NONBLOCK) | O_NONBLOCK; 1291 1292     retval = sock_create(family, type, protocol, &amp;sock); 1293     if (retval 0) 1294         goto out; 1295 1296     retval = sock_map_fd(sock, flags &amp; (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 }</code>

1272行:使用宏SYSCALL_DEFINE3定義了核心export出來的API “sys_socket”,參數是int family, int type, 和int protocol。

1279~1282行:對于這些常量作出編譯期間的檢查。

1284~1286行:在linux2.6.27以前的版本,參數int type隻能取真正的socket type的值,即下面的

<code>enum sock_type {     SOCK_STREAM    = 1,     SOCK_DGRAM    = 2,     SOCK_RAW    = 3,     SOCK_RDM    = 4,     SOCK_SEQPACKET    = 5,     SOCK_DCCP    = 6,     SOCK_PACKET    = 10, };</code>

但是在Linux 2.6.27版本以後,type有了第二個用途,它可以或上下面的兩個數,來指定socket的行為。

<code>#define SOCK_CLOEXEC    O_CLOEXEC #ifndef SOCK_NONBLOCK #define SOCK_NONBLOCK    O_NONBLOCK #endif</code>

是以,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的代碼,明天繼續吧。

繼續閱讀