IO 模型知多少 | 代码篇 (4)

从上面的输出来看,.NET Core控制台应用启动时启动了多个线程,并在10、11、29、31号文件描述符启动了socket监听。那哪一个文件描述符监听的是5001端口呢。

shengjie@ubuntu:~/coding/dotnet/Io.Demo$ cat /proc/net/tcp | grep 1389 # 查看5001端口号相关的tcp链接(0x1389 为5001十六进制) 4: 0100007F:1389 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 43429 1 0000000000000000 100 0 0 10 0 12: 0100007F:9038 0100007F:1389 01 00000000:00000000 00:00000000 00000000 1000 0 44343 1 0000000000000000 20 4 30 10 -1 13: 0100007F:1389 0100007F:9038 01 00000000:00000000 00:00000000 00000000 1000 0 42149 1 0000000000000000 20 4 29 10 -1

从中可以看到inode为[43429]的socket监听在5001端口号,所以可以找到上面的输出行lrwx------ 1 shengjie shengjie 64 5月 10 16:37 29 -> 'socket:[43429]',进而判断监听5001端口号socket对应的文件描述符为29。

当然,也可以从记录到strace目录的日志文件找到线索。在文中我们已经提及,socket服务端编程的一般流程,都要经过socket->bind->accept->read->write流程。所以可以通过抓取关键字,查看相关系统调用。

shengjie@ubuntu:~/coding/dotnet/Io.Demo$ grep 'bind' strace/ -rn strace/io.3696:4570:bind(10, {sa_family=AF_UNIX, sun_path="/tmp/dotnet-diagnostic-3696-327175-socket"}, 110) = 0 strace/io.3763:2241:bind(11, {sa_family=AF_UNIX, sun_path="/tmp/dotnet-diagnostic-3763-328365-socket"}, 110) = 0 strace/io.3763:2949:bind(29, {sa_family=AF_INET, sin_port=htons(5001), sin_addr=inet_addr("127.0.0.1")}, 16) = 0 strace/io.3713:4634:bind(11, {sa_family=AF_UNIX, sun_path="/tmp/dotnet-diagnostic-3713-327405-socket"}, 110) = 0

从上可知,在主线程也就是io.3763线程的系统调用文件中,将29号文件描述符与监听在127.0.0.1:5001的socket进行了绑定。同时也明白了.NET Core自动建立的另外2个socket是与diagnostic相关。
接下来咱们重点看下3763号线程产生的系统调用。

shengjie@ubuntu:~/coding/dotnet/Io.Demo$ cd strace/ shengjie@ubuntu:~/coding/dotnet/Io.Demo/strace$ cat io.3763 # 仅截取相关片段 socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_TCP) = 29 setsockopt(29, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 bind(29, {sa_family=AF_INET, sin_port=htons(5001), sin_addr=inet_addr("127.0.0.1")}, 16) = 0 listen(29, 10) write(21, "\346\234\215\345\212\241\347\253\257\345\267\262\345\220\257\345\212\250(127.0.0.1:500"..., 51) = 51 accept4(29, {sa_family=AF_INET, sin_port=htons(36920), sin_addr=inet_addr("127.0.0.1")}, [16], SOCK_CLOEXEC) = 31 write(21, "127.0.0.1:36920-\345\267\262\350\277\236\346\216\245\n", 26) = 26 write(21, "127.0.0.1:36920-\345\274\200\345\247\213\346\216\245\346\224\266\346\225\260\346"..., 38) = 38 recvmsg(31, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="1\n", iov_len=512}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 2 write(21, "127.0.0.1:36920-\346\216\245\346\224\266\346\225\260\346\215\256\357\274\2321"..., 34) = 34 sendmsg(31, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="received:1\n", iov_len=11}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 11 accept4(29, 0x7fecf001c978, [16], SOCK_CLOEXEC) = ? ERESTARTSYS (To be restarted if SA_RESTART is set) --- SIGWINCH {si_signo=SIGWINCH, si_code=SI_KERNEL} ---

从中我们可以发现几个关键的系统调用:

socket

bind

listen

accept4

recvmsg

sendmsg

通过命令man命令可以查看下accept4和recvmsg系统调用的相关说明:

shengjie@ubuntu:~/coding/dotnet/Io.Demo/strace$ man accept4 If no pending connections are present on the queue, and the socket is not marked as nonblocking, accept() blocks the caller until a connection is present. shengjie@ubuntu:~/coding/dotnet/Io.Demo/strace$ man recvmsg If no messages are available at the socket, the receive calls wait for a message to arrive, unless the socket is nonblocking (see fcntl(2))

也就是说accept4和recvmsg是阻塞式系统调用。

验证I/O多路复用发起的系统调用

同样以上面I/O多路复用的代码进行验证,验证步骤类似:

shengjie@ubuntu:~/coding/dotnet$ strace -ff -o Io.Demo/strace2/io dotnet run --project Io.Demo/ Press any key to start! 服务端已启动(127.0.0.1:5001)-等待连接... 127.0.0.1:37098-已连接 127.0.0.1:37098-接收数据:1 127.0.0.1:37098-接收数据:2 shengjie@ubuntu:~/coding/dotnet/Io.Demo$ nc localhost 5001 1 received:1 2 received:2 shengjie@ubuntu:/proc/2449$ netstat -natp | grep 5001 (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) tcp 0 0 127.0.0.1:5001 0.0.0.0:* LISTEN 2449/Io.Demo tcp 0 0 127.0.0.1:5001 127.0.0.1:56296 ESTABLISHED 2449/Io.Demo tcp 0 0 127.0.0.1:56296 127.0.0.1:5001 ESTABLISHED 2499/nc shengjie@ubuntu:~/coding/dotnet/Io.Demo$ ps -h | grep dotnet 2400 pts/3 S+ 0:10 strace -ff -o ./Io.Demo/strace2/io dotnet run --project Io.Demo/ 2402 pts/3 Sl+ 0:01 dotnet run --project Io.Demo/ 2449 pts/3 Sl+ 0:00 /home/shengjie/coding/dotnet/Io.Demo/bin/Debug/netcoreapp3.0/Io.Demo 2516 pts/5 S+ 0:00 grep --color=auto dotnet shengjie@ubuntu:~/coding/dotnet/Io.Demo$ cd /proc/2449/ shengjie@ubuntu:/proc/2449$ ll task total 0 dr-xr-xr-x 11 shengjie shengjie 0 5月 10 22:15 ./ dr-xr-xr-x 9 shengjie shengjie 0 5月 10 22:15 ../ dr-xr-xr-x 7 shengjie shengjie 0 5月 10 22:15 2449/ dr-xr-xr-x 7 shengjie shengjie 0 5月 10 22:15 2451/ dr-xr-xr-x 7 shengjie shengjie 0 5月 10 22:15 2452/ dr-xr-xr-x 7 shengjie shengjie 0 5月 10 22:15 2453/ dr-xr-xr-x 7 shengjie shengjie 0 5月 10 22:15 2454/ dr-xr-xr-x 7 shengjie shengjie 0 5月 10 22:15 2455/ dr-xr-xr-x 7 shengjie shengjie 0 5月 10 22:15 2456/ dr-xr-xr-x 7 shengjie shengjie 0 5月 10 22:15 2459/ dr-xr-xr-x 7 shengjie shengjie 0 5月 10 22:15 2462/ shengjie@ubuntu:/proc/2449$ ll fd total 0 dr-x------ 2 shengjie shengjie 0 5月 10 22:15 ./ dr-xr-xr-x 9 shengjie shengjie 0 5月 10 22:15 ../ lrwx------ 1 shengjie shengjie 64 5月 10 22:16 0 -> /dev/pts/3 lrwx------ 1 shengjie shengjie 64 5月 10 22:16 1 -> /dev/pts/3 lrwx------ 1 shengjie shengjie 64 5月 10 22:16 10 -> 'socket:[35001]' lr-x------ 1 shengjie shengjie 64 5月 10 22:16 100 -> /dev/random lrwx------ 1 shengjie shengjie 64 5月 10 22:16 11 -> 'socket:[34304]' lr-x------ 1 shengjie shengjie 64 5月 10 22:16 13 -> 'pipe:[31528]' l-wx------ 1 shengjie shengjie 64 5月 10 22:16 14 -> 'pipe:[31528]' lr-x------ 1 shengjie shengjie 64 5月 10 22:16 15 -> /home/shengjie/coding/dotnet/Io.Demo/bin/Debug/netcoreapp3.0/Io.Demo.dll lr-x------ 1 shengjie shengjie 64 5月 10 22:16 16 -> /home/shengjie/coding/dotnet/Io.Demo/bin/Debug/netcoreapp3.0/Io.Demo.dll lr-x------ 1 shengjie shengjie 64 5月 10 22:16 17 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/System.Runtime.dll lr-x------ 1 shengjie shengjie 64 5月 10 22:16 18 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/System.Console.dll lr-x------ 1 shengjie shengjie 64 5月 10 22:16 19 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/System.Threading.dll lrwx------ 1 shengjie shengjie 64 5月 10 22:16 2 -> /dev/pts/3 lr-x------ 1 shengjie shengjie 64 5月 10 22:16 20 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/System.Runtime.Extensions.dll lrwx------ 1 shengjie shengjie 64 5月 10 22:16 21 -> /dev/pts/3 lr-x------ 1 shengjie shengjie 64 5月 10 22:16 22 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/System.Text.Encoding.Extensions.dll lr-x------ 1 shengjie shengjie 64 5月 10 22:16 23 -> /dev/urandom lr-x------ 1 shengjie shengjie 64 5月 10 22:16 24 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/System.Net.Sockets.dll lr-x------ 1 shengjie shengjie 64 5月 10 22:16 25 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/System.Net.Primitives.dll lr-x------ 1 shengjie shengjie 64 5月 10 22:16 26 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/Microsoft.Win32.Primitives.dll lr-x------ 1 shengjie shengjie 64 5月 10 22:16 27 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/System.Diagnostics.Tracing.dll lr-x------ 1 shengjie shengjie 64 5月 10 22:16 28 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/System.Threading.Tasks.dll lrwx------ 1 shengjie shengjie 64 5月 10 22:16 29 -> 'socket:[31529]' lr-x------ 1 shengjie shengjie 64 5月 10 22:16 3 -> 'pipe:[32055]' lr-x------ 1 shengjie shengjie 64 5月 10 22:16 30 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/System.Threading.ThreadPool.dll lr-x------ 1 shengjie shengjie 64 5月 10 22:16 31 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/System.Collections.Concurrent.dll lrwx------ 1 shengjie shengjie 64 5月 10 22:16 32 -> 'anon_inode:[eventpoll]' lr-x------ 1 shengjie shengjie 64 5月 10 22:16 33 -> 'pipe:[32059]' l-wx------ 1 shengjie shengjie 64 5月 10 22:16 34 -> 'pipe:[32059]' lrwx------ 1 shengjie shengjie 64 5月 10 22:16 35 -> 'socket:[35017]' lr-x------ 1 shengjie shengjie 64 5月 10 22:16 36 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/System.Memory.dll lr-x------ 1 shengjie shengjie 64 5月 10 22:16 37 -> /dev/urandom lr-x------ 1 shengjie shengjie 64 5月 10 22:16 38 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/System.Diagnostics.Debug.dll l-wx------ 1 shengjie shengjie 64 5月 10 22:16 4 -> 'pipe:[32055]' lrwx------ 1 shengjie shengjie 64 5月 10 22:16 5 -> /dev/pts/3 lrwx------ 1 shengjie shengjie 64 5月 10 22:16 6 -> /dev/pts/3 lrwx------ 1 shengjie shengjie 64 5月 10 22:16 7 -> /dev/pts/3 lr-x------ 1 shengjie shengjie 64 5月 10 22:16 9 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/3.0.0/System.Private.CoreLib.dll lr-x------ 1 shengjie shengjie 64 5月 10 22:16 99 -> /dev/urandom shengjie@ubuntu:/proc/2449$ cat /proc/net/tcp | grep 1389 0: 0100007F:1389 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 31529 1 0000000000000000 100 0 0 10 0 8: 0100007F:1389 0100007F:DBE8 01 00000000:00000000 00:00000000 00000000 1000 0 35017 1 0000000000000000 20 4 29 10 -1 12: 0100007F:DBE8 0100007F:1389 01 00000000:00000000 00:00000000 00000000 1000 0 28496 1 0000000000000000 20 4 30 10 -1

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfjwg.html