Linux核心建立socket的過程
Ok,就讓我們來看看這socket背後的故事吧。
1.使用者程式首先呼叫socket()系統呼叫,其原型為:
int socket(int domain, int type, int protocol)
2.我們呼叫的socket()系統呼叫其實是glic這個庫提供的,glic內部會執行實際的系統呼叫。
我們可以看一下glic的內部實現。
檔案sysdeps/unix/sysv/linux/i386/socket.S
點選(此處)摺疊或開啟
-
.globl __socket
-
ENTRY (__socket)
-
#if defined NEED_CANCELLATION &
-
SINGLE_THREAD_P
-
jne 1f
-
#endif
-
/* 儲存ebx暫存器的值 */
-
movl %ebx, %edx
- cfi_register (3, 2)
- /* 把系統呼叫的呼叫號放到eax暫存器裡 */
- movl $SYS_ify(socketcall), %eax
- /* 傳給syscall的第一個引數是子code,用來識別是哪一個socket系統呼叫 */
- movl $P(SOCKOP_,socket), %ebx
-
/* 第二個引數是使用者態傳遞的引數陣列的地址 */
-
lea 4(
-
/* 執行系統呼叫 */
-
ENTER_KERNEL
-
/* 恢復ebx暫存器 */
-
movl %edx, %ebx
-
cfi_restore (3)
-
/* 如果發生了錯誤,%eax小於0 */
-
cmpl $-125, %eax
-
jae SYSCALL_ERROR_LABEL
-
/* 成功的話返回系統呼叫的結果 */
-
L(pseudo_end):
- ret
3.當核心收到系統呼叫的命令以後,會從eax暫存器中取出系統呼叫號,然後在sys_call_table
這個表中查詢對應的處理系統呼叫的函式,具體過程不再贅述。
核心會呼叫sys_socketcall()來處理。
檔案net/socket.c
點選(此處)摺疊或開啟
-
asmlinkage long sys_socketcall(int call, unsigned
long __user *args)
-
{
-
unsigned long a[6];
-
unsigned long a0, a1;
-
int err;
-
if (call < 1 || call > SYS_ACCEPT4)
-
return -EINVAL;
-
/* 呼叫copy_from_user函式,從使用者空間的記憶體地址拷貝引數到核心空間 */
-
if (copy_from_user(a, args, nargs[call]))
-
return -EFAULT;
-
err = audit_socketcall(nargs[call] / sizeof(unsigned
long), a);
-
if (err)
-
return err;
-
a0 = a[0];
-
a1 = a[1];
-
switch (call) {
-
case SYS_SOCKET:
-
err = sys_socket(a0, a1, a[2]);
-
break;
-
case SYS_BIND:
-
err = sys_bind(a0, (struct
sockaddr __user *)a1, a[2]);
-
break;
-
case SYS_CONNECT:
-
err = sys_connect(a0, (struct
sockaddr __user *)a1, a[2]);
-
break;
-
case SYS_LISTEN:
-
err = sys_listen(a0, a1);
-
break;
-
case SYS_ACCEPT:
-
err = sys_accept4(a0, (struct
sockaddr __user *)a1,
-
(int __user *)a[2], 0);
-
break;
-
case SYS_GETSOCKNAME:
-
err =
-
sys_getsockname(a0, (struct sockaddr __user *)a1,
-
(int __user *)a[2]);
-
break;
-
case SYS_GETPEERNAME:
-
err =
-
sys_getpeername(a0, (struct sockaddr __user *)a1,
-
(int __user *)a[2]);
-
break;
-
case SYS_SOCKETPAIR:
-
err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
-
break;
-
case SYS_SEND:
-
err = sys_send(a0, (void
__user *)a1, a[2], a[3]);
-
break;
-
case SYS_SENDTO:
-
err = sys_sendto(a0, (void
__user *)a1, a[2], a[3],
-
(struct sockaddr __user *)a[4], a[5]);
-
break;
-
case SYS_RECV:
-
err = sys_recv(a0, (void
__user *)a1, a[2], a[3]);
-
break;
-
case SYS_RECVFROM:
-
err = sys_recvfrom(a0, (void
__user *)a1, a[2], a[3],
-
(struct sockaddr __user *)a[4],
-
(int __user *)a[5]);
-
break;
-
case SYS_SHUTDOWN:
-
err = sys_shutdown(a0, a1);
-
break;
-
case SYS_SETSOCKOPT:
-
err = sys_setsockopt(a0, a1, a[2], (char
__user *)a[3], a[4]);
-
break;
-
case SYS_GETSOCKOPT:
-
err =
-
sys_getsockopt(a0, a1, a[2], (char
__user *)a[3],
-
(int __user *)a[4]);
-
break;
-
case SYS_SENDMSG:
-
err = sys_sendmsg(a0, (struct
msghdr __user *)a1, a[2]);
-
break;
-
case SYS_RECVMSG:
-
err = sys_recvmsg(a0, (struct
msghdr __user *)a1, a[2]);
-
break;
-
case SYS_ACCEPT4:
-
err = sys_accept4(a0, (struct
sockaddr __user *)a1,
-
(int __user *)a[2], a[3]);
-
break;
-
default:
-
err = -EINVAL;
-
break;
-
}
-
return err;
- }
因為我們呼叫的是socket()系統呼叫,所以會執行sys_socket()這個函式。
4.核心呼叫sys_socket()來處理建立socket的系統呼叫。
檔案net/socket.c
點選(此處)摺疊或開啟
-
asmlinkage long sys_socket(int family, int type, int protocol)
-
{
-
int retval;
-
struct socket *sock;
-
int flags;
-
/* Check the SOCK_* constants for consistency. */
-
BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
-
BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
-
BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
-
BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
-
flags = type & ~SOCK_TYPE_MASK;
-
if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
-
return -EINVAL;
-
type &= SOCK_TYPE_MASK;
-
if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
-
flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
-
/* 實際建立socket */
-
retval = sock_create(family, type, protocol, &sock);
-
if (retval < 0)
-
goto out;
-
/* 把建立的socket對映到檔案描述符 */
-
retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
-
if (retval < 0)
-
goto out_release;
-
out:
-
/* It may be already another descriptor 8) Not kernel
problem. */
-
return retval;
-
out_release:
-
sock_release(sock);
-
return retval;
- }
相關推薦
Linux核心建立socket的過程
當我們呼叫socket()這個系統呼叫的時候,Linux核心究竟做了哪些事情呢? Ok,就讓我們來看看這socket背後的故事吧。 1.使用者程式首先呼叫socket()系統呼叫,其原型為:int socket(int domain, int type, int proto
《Linux作業系統分析》之分析Linux核心建立一個新程序的過程
本篇文章通過fork函式的呼叫,來說明在Linux系統中建立一個新程序需要經歷的過程。 相關知識: 首先關於這篇文章會介紹一些用到的知識。 一、程序、輕量級程序、執行緒 程序是程式執行的一個例項。程序的目的就是擔當分配系統資源的實體。 兩個輕量級程序基本可以共享一些資源,比
arm的2級頁表在Linux核心建立過程解析
系統DDR的基地址為0x0,記憶體為1GB,所以TTB的基地址為0x4000。下面要建立虛擬地址0xfe700000到實體地址0xffff0000之間的對映,對映大小為64KB,即16頁。由於實體地址不是1MB位元組對齊,所以必須建立兩級對映。 使用者空間/核心空間
Linux核心建立一個程序的過程分析
不管在什麼系統中,所有的任務都是以程序為載體的,所以理解程序的建立對於理解作業系統的原理是非常重要的,本文是我在學習linux核心中所做的筆記,如有錯誤還請大家批評指正。注:我所閱讀的核心版本是0.11。 一、關於PCB 對於一個程序來說,PCB就好像是他的
對linux核心建立flash上的各分割槽原始碼進行分析
1.注意:核心原始碼版本為4.9 2.首先注意關鍵字串"partitions found on MTD device 這句話在drivers/mtd/mtdpart.c的parse_mtd_partitions()中出現 3.mtd_device_parse_register()呼叫了parse_mtd
linux核心——建立自己的/proc檔案——processinfo
利用proc_mkdir()建立一個mydir,再利用create_proc_read_entry()函式建立一個processinfo檔案。我們從模組裡面獲取的資訊都將寫入到processinfo檔案中。 #include<linux/module.h> #i
linux核心的生成過程, vmlinux除錯分析
1. 依據arch/arm/kernel/vmlinux.lds 生成linux核心原始碼根目錄下的vmlinux,這個vmlinux屬於未壓縮,帶除錯資訊、符號表的最初的核心,大小約23MB; arm-linux-gnu-ld -EL -p --no-undefined -X -o vmlinux
基於PPC64架構 Linux 核心訊號處理過程棧處理分析
handle_rt_signal64主要負責訊號處理棧處理分析,如下圖所示 int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user
Linux SSH建立連線過程分析
SSH建立連線的過程主要分為下面幾個階段: SSH協議版本協商階段。SSH目前包括SSH1和SSH2兩個大版本。金鑰和演算法協商階段,SSH支援多種加密演算法,雙方根據自己和對端支援的演算
Linux核心初始化過程的原始碼分析疑點記錄+好書推薦(附下載)
這個對基於PowerPC的Linux核心原始碼剖析的文章已經寫了三篇了(見前三篇博文),由於可以找到的關於PowerPC E300處理器的Linux文章基本沒有,這些都是一點點摸索的,可能存在不少的錯誤,特別是第3篇,自我感覺很差,開始計劃寫這個系列的時候,自以為已
Linux核心執行緒(kthread)建立過程
我們在核心中建立並執行核心執行緒,直接呼叫kthread_run巨集就可以實現。其原型為: /** * kthread_run - create and wake a thread. * @threadfn: the function to run unti
linux核心中socket的建立過程原始碼分析(總結性質)
http://www.jianshu.com/p/5d82a685b5b6 在漫長地分析完socket的建立原始碼後,發現一片漿糊,所以特此總結,我的部落格中同時有另外一篇詳細的原始碼分析,核心版本為3.9,建議在閱讀本文後若還有興趣再去看另外一篇博文。絕對不要單獨看另外
Linux核心Socket CAN中文文件
轉載地址:https://blog.csdn.net/zhangxiaopeng0829/article/details/7646639 自己在年假中空閒之餘翻譯的核心中Socket CAN的文件,原文地址在: http://lxr.linux.no/linux+v2.6.34/Docume
建立、編輯linux核心工程
用過source insight、vim(未使用外掛)建立編寫linux核心工程,一直想找個更合適的工具。畢竟,source insight是商業軟體,而vim如果不使用外掛還是不怎麼方便。瞭解到vim和emacs都可以用外掛構建出原始碼工程,嘗試過emacs沒能成功,也許是我用vim已經習慣了,最
linux 核心學習過程(1)-硬體特性和核心設計之間的聯絡
該貼用來作為自己學習linux核心的記錄和筆記,很多東西都是自己理解後整理的內容,各位看官若覺得有問題的地方,可以留言或自行查閱。 linux核心在設計的過程中很多都是依據硬體晶片特性來設計,晶片在設計的過程中很多時候需要保持相容性,這樣就留下了很多令人費解的概念,比如分段和分頁機制,
Linux核心啟動過程分析(十)-----RTC驅動分析
參考https://blog.csdn.net/xuao20060793/article/details/46433263這篇博文 RTC驅動分析: Class.c (drivers\rtc):subsys_initcall(rtc_init); static int __init
linux核心編譯過程的最終總結版
一、實驗目的 學習重新編譯Linux核心,理解、掌握Linux核心和發行版本的區別。 二、實驗內容 在Linux作業系統環境下重新編譯核心。實驗主要內容: A. 查詢並且下載一份核心原始碼,本實驗使用最新的Linux核心2.6.36。 B. 配置核心。 C.
走進Linux核心網路 套接字的祕密—socket與sock
雙十一 今天是雙十一,記得還在念書的時候,每次都會參加京東圖書滿200-100的活動,然後腦子一熱屯一堆書。印象中人文類的書基本都會看,而電子資訊類的可能就只看了一半,甚至買過哪些都忘了。究其原因,主要是人文類的通常都是自己想看的,而技術類的就跟風看哪個銷量大買
Linux核心分析_UDP協議中資料包的收發處理過程
1.前言 實驗基於Linux kernel 3.18.6,實驗內容包括: (1)編寫UDP客戶端和服務端 (2)將UDP客戶端和服務端整合到MenuOS中 (3)UDP傳送資料的過程 (4)UDP接收資料的過程 本文中完整原始碼:https://github.com
開啟linux核心自帶的模擬i2c-gpio模組過程
首先我們要知道核心的makefile是根據配置檔案,也就是kconfig來決定是否編譯一個檔案的。 如果沒有配置核心編譯它,就不會生成.o檔案。 自然就不會開啟這個模組了。 如下是Kconfig 檔