Where Is The Linux Socket Implementation

Where is the Linux socket implementation?

The header file contains declarations for socket-related system calls. To start diving into the implementation, please consider referring to net/socket.c file in the Linux source tree.

Regarding changing the implementation - Linux is an open-source software product distributed under the terms of GNU GPL. If you'll spend quite some time to understand how to re-build the kernel from scratch, you'll be able to apply any changes you want to the kernel and deploy it to your local machines (at your own risk of course).

Location of socket() function implementation in linux

Acutally,
int socket (int __domain, int __type, int __protocol) __THROW

implemented in glibc,

and the glibc calls the kernel function sys_socket implemented in kernel file net/socket.c.

asmlinkage long sys_socket(int family, int type, int protocol);

Where's glibc's socket implementation at?

There's a couple of things going on here.

First, as explained in this answer, glibc itself cannot define random identifiers that standard C does not reserve, because standard C allows programs to define those identifiers itself. Names beginning with a double underscore are reserved for the implementation, so the implementation here defines the function __send(). The weak alias then allows the name send() to be used to refer to it, but also allows that reference to be overridden by a strong definition somewhere else.

Second, as explained in the glibc documentation, for ease of porting glibc requires any machine-specific function to have a corresponding generic function. If a corresponding generic function can be written, then it should be, but if not, the generic one should be a "stub function", which essentially just sets errno to ENOSYS (not implemented) and returns an error. If there is a machine-specific function provided, that'll be used instead of the stub function. Since send() requires a system call, obviously it cannot be written in a machine-independent way, so there's a stub function for it here. So you should be able to locate a machine-specific implementation (or a variety of them) of __send(), for instance, at /sysdeps/unix/sysv/linux/x86_64/send.c in the glibc source tree.

Incidentally, since send() is indeed a system call, all you're typically going to see in glibc is a short assembly language routine that makes the system call. The code that actually does stuff will live in the kernel.

Where is socket create function implemented in linux

Look on kernel.org for the authentic kernel source. Understand that socket(2) is one of the many syscalls(2) (you need to understand precisely what system calls are) so it is implemented inside the kernel as sys_socket and/or sys_socketcall and/or do_socket; sockets and network code are an entire subsystem (net/) of the kernel, so see its net/socket.c, etc etc... See also socketcall(2)

Application user-side code are simply issuing a syscall, so socket(2) is a thin wrapper around a system call (in GNU libc or musl-libc or whatever implementation of the C standard library you are using). See also this.

Linux 'socketcall' system call implementation

man 2 socketcall says that

NOTES
On a few architectures, for example ia64, there is no socketcall() system call; instead socket(2), accept(2), bind(2), and so on really
are implemented as separate system calls

So, in the case of x86, the socketcall dispatcher is only for x86_32, while x86_64 uses separate system calls for each socket API.

Linux x86_64 assembly socket programming

The 64 bit calling convention does use registers to pass arguments, both in user space and to system calls. As you have seen, the user space convention is rdi,rsi, rdx, rcx, r8, r9. For system calls, r10 is used instead of rcx which is clobbered by the syscall instruction. See wikipedia or the ABI documentation for more details.

The definitions of the various constants are hidden in header files, which are nevertheless easily found via a file system search assuming you have the necessary development packages installed. You should look in /usr/include/x86_64-linux-gnu/bits/socket.h and /usr/include/linux/in.h.

As for a system call list, it's trivial to google one, such as this. You can also always look in the kernel source of course.

Issues with i/o calls over TCP socket

In the r_read() function, we never read in the value the server put into the response. We're only reading in the 8 bytes corresponding to the return_value and errno.

Instead of

int bytes = 0;
int total = 0;
while ( total < L ) {
if ( (bytes = write(sock, msg + total, L - total)) < 0) {
printf("Failed to send r_read to server\n");
return -1;
}
total += bytes;
}

bytes = 0;
total = 0;
while ( total < 8 ) {
if ( (bytes = read(sock, msg + total, 8 - total)) < 0) {
printf("Failed to receive r_read from server\n");
return -1;
}
total += bytes;
}

in_msg = (msg[0] << 24) | (msg[1] << 16) | (msg[2] << 8) | msg[3];
in_err = (msg[4] << 24) | (msg[5] << 16) | (msg[6] << 8) | msg[7];
for (int i = 0; i < count; i++) {
*(char *)(buf + i) = msg[i + 8];
}

We need to do

int bytes = 0;
int total = 0;
while ( total < L ) {
if ( (bytes = write(sock, msg + total, L - total)) < 0) {
printf("Failed to send r_read to server\n");
return -1;
}
total += bytes;
}

bytes = 0;
total = 0;
while ( total < 8 ) {
if ( (bytes = read(sock, msg + total, 8 - total)) < 0) {
printf("Failed to receive r_read from server\n");
return -1;
}
total += bytes;
}

in_msg = (msg[0] << 24) | (msg[1] << 16) | (msg[2] << 8) | msg[3]; // # of bytes remaining in the socket buffer (the data we asked for)
in_err = (msg[4] << 24) | (msg[5] << 16) | (msg[6] << 8) | msg[7];

bytes = 0;
total = 0;
while ( total < in_msg ) {
if ( (bytes = read(sock, buf + total, in_msg - total)) < 0) {
printf("Failed to read the r_read data from server\n");
return -1;
}
}

Note that the while ( total ...) logic is only required if you're needing to handle a case where a read or write call does not fully succeed. In my case, we're allowed to simply exit with an error if this happens.



Related Topics



Leave a reply



Submit