0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

网络套接字系统调用如何到达sys_socketcall

麦辣鸡腿堡 来源:技术简说 作者:技术简说 2023-07-24 11:35 次阅读

套接字系统调用如何到达sys_socketcall

accept函数为例

系统调用中参数从用户态向内核态的传递是通过寄存器完成的,eax表示系统调用,ebx表示第一个参数,ecx表示第二个参数,edx表示第三个参数(主要针对socke.S)

第一层:accept.s文件

(glibc函数库)sysdepsunissysvlinuxaccept.S

#define socket accept    //将socket定义为accept
#define _socket _libc_accept
#define NARGS 3           //系统调用的个数
#include < socket.S >     //这几个套接字函数的通用实现

第二层:socket.S文件

#include < sysdep.h >
#include < sys/socketcall.h >

#define P(a, b) P2(a, b)
#define P2(a, b) a##b

.text
/* The socket-oriented system calls are handled unusally in Linux.
  They are all gated through the single `socketcall' system call number.
  `socketcall' takes two arguments: the first is the subcode, specifying
  which socket function is being called; and the second is a pointer to
  the arguments to the specific function.

  The .S files for the other calls just #define socket and #include this. */

.globl P(__,socket)
ENTRY (P(__,socket))

/* Save registers. */
movl %ebx, %edx

movl $SYS_ify(socketcall), %eax/* System call number in %eax. */
//展开$SYS_iff()宏
/* Use ## so `socket' is a separate token that might be #define'd. */
movl $P(SOCKOP_,socket), %ebx/* Subcode is first arg to syscall. */
lea 4(%esp), %ecx/* Address of args is 2nd arg. */

       /* Do the system call trap. */
int $0x80

/* Restore registers. */
movl %edx, %ebx

/* %eax is < 0 if there was an error. */
cmpl $-125, %eax
jae syscall_error

/* Successful; return the syscall's value. */
ret

PSEUDO_END (P(__,socket))
c
weak_alias (P(__,socket), socket)

重点看:

movl $SYS_ify(socketcall), %eax /* System call number in %eax. */

展开SYS_iff()宏 (glibc函数库: sysdepsunixsysdep.h)

#ifdef __STDC__
#define SYS_ify(syscall_name) SYS_##syscall_name
#else
#define SYS_ify(syscall_name) SYS_/**/syscall_name
#endif

预处理后为:

movl $SYS_socketcall,%eax
//将系统调用号放入eax中,但是对于网络套接字所有的接口函数而言,他们的共同入口函数是sys_socketcall
//在内核中,总入口函数sys_socketcall的系统调用号为_NR_socketcall,定义在include/linux/unistd.h
#define __NR_socketcall102
//在glib函数库中,有如下的预定义
#define SYS_socketcall _NR_socketcall

所以:

movl $SYS_socketcall,%eax
//将sys_socketcall函数对应的系统调用号赋予eax寄存器,从而使套接字系统调用进入到正常的入口函数中

这样套接字系统调用进入到正确的函数中了。

那么第一个参数是识别系统调用的具体函数的,这个参数在socket.S(glibc库)中:

movl $P(SOCKOP_,socket), %ebx
//预处理后:
movl $SOCKOP_accept,%ebx//这就完成了第一个参数的传递

关于SOCKOP_accept:

查看(glibc库:sysdepsunixsysvlinuxsocketcall.h)

#ifndef _SYS_SOCKETCALL_H

#define _SYS_SOCKETCALL_H	1

/* Define unique numbers for the operations permitted on socket.  Linux
   uses a single system call for all these functions.  The relevant code
   file is /usr/include/linux/net.h.
   We cannot use a enum here because the values are used in assembler
   code.  */

#define SOCKOP_socket		1
#define SOCKOP_bind		2
#define SOCKOP_connect		3
#define SOCKOP_listen		4
//可以看到SOCKOP_accept对应的值为5
#define SOCKOP_accept		5
#define SOCKOP_getsockname	6
#define SOCKOP_getpeername	7
#define SOCKOP_socketpair	8
#define SOCKOP_send		9
#define SOCKOP_recv		10
#define SOCKOP_sendto		11
#define SOCKOP_recvfrom		12
#define SOCKOP_shutdown		13
#define SOCKOP_setsockopt	14
#define SOCKOP_getsockopt	15
#define SOCKOP_sendmsg		16
#define SOCKOP_recvmsg		17

#endif /* _SYS_SOCKETCALL_H */

在linux内核(include/linux/net.h):

#ifndef _SYS_SOCKETCALL_H

#define _SYS_SOCKETCALL_H	1

/* Define unique numbers for the operations permitted on socket.  Linux
   uses a single system call for all these functions.  The relevant code
   file is /usr/include/linux/net.h.
   We cannot use a enum here because the values are used in assembler
   code.  */

#define SOCKOP_socket		1
#define SOCKOP_bind		2
#define SOCKOP_connect		3
#define SOCKOP_listen		4
//这与glibc库中的SOCKOP_accept对应的值相同
#define SOCKOP_accept		5
#define SOCKOP_getsockname	6
#define SOCKOP_getpeername	7
#define SOCKOP_socketpair	8
#define SOCKOP_send		9
#define SOCKOP_recv		10
#define SOCKOP_sendto		11
#define SOCKOP_recvfrom		12
#define SOCKOP_shutdown		13
#define SOCKOP_setsockopt	14
#define SOCKOP_getsockopt	15
#define SOCKOP_sendmsg		16
#define SOCKOP_recvmsg		17

#endif /* _SYS_SOCKETCALL_H */

第二个参数

在socket.S中:以指针的方式设置了sys_socketcall的第二个参数

lea 4(%esp), %ecx		/* Address of args is 2nd arg.  */

设置完以上的系统调用号还有参数后进入软中断:int $0x80,进入了内核态进行处理

第三层:entry.S文件

_system_call:
	pushl %eax			# save orig_eax
	SAVE_ALL
	movl $-ENOSYS,EAX(%esp)
	cmpl $(NR_syscalls),%eax
	jae ret_from_sys_call
    /*对应上面,未调用软中断之前,eax寄存器中被初始化为系统调用号,即_NR_socketcall,
       这个调用号别用于在_sys_call_table数组中进行函数指针的寻址,将对应的函数地址对eax寄存器赋值      */
	movl _sys_call_table(,%eax,4),%eax
	testl %eax,%eax
	je ret_from_sys_call
	movl _current,%ebx
	andl $~CF_MASK,EFLAGS(%esp)	# clear carry - assume no errors
	movl $0,errno(%ebx)
	movl %db6,%edx
	movl %edx,dbgreg6(%ebx)  # save current hardware debugging status
	testb $0x20,flags(%ebx)		# PF_TRACESYS
	jne 1f
    /*上面给eax复制后,这里进行调用该函数,到这为止,accept系统调用将请求传递给了sys_socketcall,
        然后将socket.S中设置的参数传递给sock_accept函数,就完成了应用层接口函数accept到BSD socket层函数的请求传递工作
        */
	call *%eax
	movl %eax,EAX(%esp)		# save the return value
	movl errno(%ebx),%edx
	negl %edx
	je ret_from_sys_call
	movl %edx,EAX(%esp)
	orl $(CF_MASK),EFLAGS(%esp)	# set carry to indicate error
	jmp ret_from_sys_call
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    30

    文章

    5032

    浏览量

    117741
  • 函数
    +关注

    关注

    3

    文章

    3882

    浏览量

    61310
  • 系统
    +关注

    关注

    1

    文章

    981

    浏览量

    21036
收藏 人收藏

    评论

    相关推荐

    【MiCOKit试用体验】庆科MiCO系统篇(5)MiCO 套接

    管理协议)、DNS(主域名称系统)、TFTP(通用文件传输协议)等。TCP的通信机制大体可如下图所示UDP的通信机制大体可如下图所示二 MiCOKit套接在MiCOKit中,有关Socket
    发表于 10-24 17:05

    UNIX域套接

    UNIX域套接用于在同一台计算机上运行的进程之间的通信。虽然因特网域套接可用于同一目的,但UNIX域套接
    发表于 09-02 11:59

    命名UNIX域套接

    虽然socketpair函数能创建一对相互连接的套接,但是每一个套接都没有名字。这意味着无关进程不能使用它们。如果我们试图绑定同一地址时,该文件已经存在,那么bind请求会失败。当
    发表于 09-02 14:45

    vrf套接通信

    ;大家好,>我想要做的是通过socket>连接从PC通信到UNIX盒子。我希望PC在UNIX系统上执行命令并>通过套接连接检索结果。例如,有一个命令>'whatRev'将显示某些
    发表于 09-05 09:42

    端点和套接怎么配置

    我有3个端点2个散列端点和1个端点。我想实现一个SLaveFIFO接口。是否有一个消费者的P-端口套接足以将数据从2个输出端点传输出去,我是否应该创建另一个消费者P-端口套接?提前
    发表于 02-12 14:00

    交换机网络从Soft_AP到Infrastructure后,套接始终返回无效

    与以下代码的客户端连接通过这个实现,TCPPOEN函数返回一个有效的套接,但是在进入无限循环之后,我们通过在网页中配置网络来配置网络处于基础结构模式。当
    发表于 04-24 09:57

    STM32例程能否与MFC网络套接通信?

    如题。。想自己写一个PC上的MFC界面。不要求太高的实时性和过大过高的传输数据量,偶尔一次传输几十节即可,不知道STM32例程能否与MFC网络套接通信。如果可以就入手一套了,另外,
    发表于 08-02 04:36

    没有操作系统真的不能使用LwIP套接和域名解析吗?

    裸机移植了LwIP协议栈,整体感觉不错但是在使用套接(Socket)功能和域名解析(lwip_gethostbyname)时发现编译通不过,说是要启用操作系统。如果不用操作系统就只能
    发表于 08-22 22:25

    Harmony堆栈为什么会立即终止套接吗?

    配置了20个NET_PRES套接、8个BSD套接和20个TCPIP套接。TCPIP堆为64
    发表于 03-19 10:43

    如何使用Lwip套接发送和接收巨型帧?

    。所以我启用了巨型帧并在BSP中将MTU大小更改为8192并尝试发送4K数据。我的套接应用程序正在发送数据但系统没有收到任何内容。经过大量的搞乱后,我找到了解决方案,该解决方案与Windows
    发表于 04-03 09:55

    如何通过socket系统调用创建一个套接

    。服务器端:首先服务器 应用程序通过socket系统调用创建一个套接,他是系统分配给该服务器进程的类似文件描述符的资源,不能和其他进程分享
    发表于 12-24 06:38

    一文读懂RT-Thread的SAL套接抽象层

    SAL 简介为了适配更多的网络协议栈类型,避免系统对单一网络协议栈的依赖,RT-Thread 系统提供了一套 SAL(套接
    发表于 04-08 15:44

    RTT网络框架及SAL套接抽象层介绍

    基于自己对各层级的理解,作为划分依据。应用编程、协议栈与网卡驱动首先请允许我简单粗暴地把所有基于协议栈应用接口开发的相关代码,都归属于应用编程下,在带操作系统的情况下,通常协议栈都会提供套接
    发表于 07-28 11:40

    如何在iMXRT1176上的LwIP中使用TCP套接

    使用原始 API) 2) OS模式可以使用Socket API和Raw API 3) lwip_ping_freertos 示例使用套接 API 我的问题是,在创建套接期间,它使用
    发表于 06-02 10:10

    网络系统调用网络套接字入口函数

    网络套接字入口函数 //所有的网络套接系统调用函数(socket bind listen co
    的头像 发表于 07-24 11:02 273次阅读