1、C语言测试代码:
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <err.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>#define BSIZE 0x1000/* "BSIZE" is the size of the buffer we use to read from the socket. */ int main ()
{struct addrinfo hints, *res;int socketfd;char *msg;int bytes;char buf[BSIZE+10];memset (&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC;hints.ai_socktype = SOCK_STREAM;//套接字流方式tcp/* Get one of the web pages here. //www.lemoda.net*/socketfd = getaddrinfo ("www.lemoda.net", "http", &hints, &res);//获取主机地址信息if (socketfd) {fprintf (stderr, "%s\n", gai_strerror(socketfd));exit (1);}//建立socketsocketfd = socket (AF_INET, SOCK_STREAM, 0);if (socketfd < 0) {fprintf (stderr, "socket: %s\n", strerror (errno));exit (1);}//链接socketif (connect(socketfd, res->ai_addr, res->ai_addrlen) < 0) {fprintf (stderr, "connect: %s\n", strerror (errno));close(socketfd);exit (1);}if (socketfd == -1) exit (1);/* "format" is the format of the HTTP request we send to the web server. */ const char * format = "GET /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: fetch.c\r\n\r\n";asprintf (&msg, format, "momoe/", "www.lemoda.net");send (socketfd, msg, strlen (msg), 0);bytes = recvfrom (socketfd, buf, BSIZE, 0, 0, 0);if (bytes == -1) {fprintf (stderr, "%s\n", strerror(errno));exit (1);}buf[bytes] = '\0';printf ("Get data from remote: \n%s\n", buf);free (msg); freeaddrinfo (res);return 0;
}
2、执行成功后内核打印日志:
完整日志:
p01-network/tcp/kern_2024_11_05_22_04_24_run_test.sh_a.out.log · r77683962/linux-6.9.0-testlog - Gitee.com
基于完整日志过滤" a.out "后的日志,因为第1步c代码编译出来的可执行文件叫a.out,执行时内核中的进程名是a.out
01-network/tcp/kern_2024_11_05_22_04_24_a.out_grep.log · r77683962/linux-6.9.0-testlog - Gitee.com
3、梳理出来的函数调用关系(从系统调用到驱动层):
SYSCALL_DEFINE6(sendto
__sys_sendto
__sock_sendmsg
sock_sendmsg_nosec
netlink_sendmsg
netlink_alloc_large_skb
netlink_unicast
netlink_unicast_kernel
sock_put
netlink_deliver_tap_kernel
netlink_deliver_tap
__netlink_deliver_tap
__netlink_deliver_tap_skb
dev_queue_xmit Y
__dev_queue_xmit Y
__dev_xmit_skb
sch_direct_xmit
dev_hard_start_xmit Y
dev_hard_start_xmit
xmit_one Y
netdev_start_xmit
__netdev_start_xmit
e1000_xmit_frame
4、将第3步的调用关系转换成源代码调用关系:
到这步其实已经到驱动层了。