雙十一
今天是雙十一,記得還在念書的時候,每次都會參加京東圖書滿200-100的活動,然後腦子一熱屯一堆書。印象中人文類的書基本都會看,而電子資訊類的可能就只看了一半,甚至買過哪些都忘了。究其原因,主要是人文類的通常都是自己想看的,而技術類的就跟風看哪個銷量大買哪個,比如下面這本《unix 網路程式設計》
如果現在讓我給別人推薦學習網路程式設計的書,我一定不會推薦這本。為什麼呢? 倒不是因為書中內容說的不對,而是我認為這本書更適合當工具書查閱,而不適合逐章學習。就像《新華字典》裡漢字很多,但也沒見誰是用它來學認字的。不過,對於當年的我來說,《unix 網路程式設計》中提供的例子倒也能提供最基本的套接字程式設計體驗。比如從中我第一次接觸到了套接字注 的概念,也接觸到了 socket(),bind() , listen(),accept(),send() , recv() 這些函式的使用方法。不過有些問題當時的我並不明白,比如建立套接字時為什麼要返回乙個描述符,為什麼傳送接收時要填寫這個描述符,難道套接字就是這個描述符?
套接字究竟是什麼
如果你知道linux系統中程序間通訊的方式,就應該知道套接字也是其中一種。但套接字特別之處在於它不僅可以用來實現同一臺主機上程序間的通訊,還可以用來實現主機間的程序間的通訊。通訊的雙方各自開啟乙個套接字,套接字之間通過通訊鏈路相連。
如果把兩個套接字之間的『連線』比喻成『水管』,那麼套接字就是『水龍頭』
unix有一句格言:everything is a file,即『萬物皆檔案』,套接字也不例外。那麼如何把套接字和檔案聯絡起來呢? 答案就是通過下面這張圖。
其中task_struct表示乙個程序,files_struct中的fd_array表示該程序開啟的所有描述符,對於套接字來說,與其他型別檔案的區別就是最終f_op指向的是socket_file_ops。不過,可以看到,這裡的socket_file_ops只有一些通用的操作,並沒有send和recv。特有的操作通過 socketcall() 區分的。
socket 和 sock
終於到今天的主角了。實際上,對每乙個新建立的套接字,核心協議棧都會建立struct socket和struct sock兩個資料結構。這兩個結構就像孿生兄弟,struct socket面向使用者空間,struct sock面向核心空間。
struct socket
struct socket簡化版的結構如下:
struct socket ;12
3456
78其中type表示協議,這是在建立套接字的時候的protocol引數確定的
int socket(int domain, int type, int protocol);
1file指標指向上面那張圖中的struct file結構,通過它,socket便與檔案系統關聯了起來。
sk指向孿生的兄弟sock結構。
socket結構中最重要的要數ops指標了,根據協議型別,它指向一種特定協議的實現。比如tcp的就是inet_stream_ops,icmp、udp協議對應inet_dgram_ops,rawip對應的是inet_sockraw_ops同樣地,這些也都在建立套接字的時候就決定了。
struct proto_ops的簡化版本的結構如下
struct proto_ops12
3456
78其中的介面名字是不是很熟悉?是的,它們和進行網路程式設計時呼叫的c庫中函式名字是一樣的。以sendmsg為例,真實的呼叫過程是這樣
即當使用者呼叫sendmsg時,核心會找到描述符fd對應的struct socket結構,然後呼叫sock->ops->sendmsg執行特定協議的傳送。
那麼,ops欄位什麼時候被賦值呢?答案是,在建立struct sock結構前。
struct sock
struct sock的簡化結構如下圖所示
struct sock_common ;
struct sock ;12
3456
789其中最重要的字段就是skc_prot,它也是協議相關的。作為struct socket結構的孿生兄弟,struct sock結構也是在使用者建立套接字時就建立的。
sock_alloc建立了struct socket結構,隨後,根據使用者傳入的family,查詢陣列net_families,找到對應的函式指標,呼叫create.
net_families儲存著核心啟動時註冊(通過sock_register)的 socket protocol handler,比如以下幾種:
static const struct net_proto_family inet_family_ops = ;
static const struct net_proto_family netlink_family_ops = ;
static const struct net_proto_family packet_family_ops = ;
static const struct net_proto_family unix_family_ops = ;12
3456
78910
1112
1314
1516
1718
1920
如果我們建立套接字時指定的family是pf_inet,那麼此時我們就會呼叫inet_create
static int inet_create(struct net *net, struct socket *sock, int protocol,
int kern)
else
if (ipproto_ip == answer->protocol)
break;
}err = -eprotonosupport;
}sock->ops = answer->ops;
sk = sk_alloc(net, pf_inet, gfp_kernel, answer_prot, kern);
if (sk->sk_prot->init) }1
2345
6789
1011
1213
1415
1617
1819
2021
2223
2425
2627
2829
30首先是從inetsw陣列搜尋匹配對應的協議,inetsw稱為協議開關表,核心啟動時,通過inet_register_protosw進行註冊。比如下面幾項都會被註冊
inetsw中註冊的每種協議都有ops和prot兩個字段,前者與struct socket結構關聯到一起,後者與struct sock關聯到一起。在inet_create中,struct socket的ops欄位和struct sock的sk_prot欄位被賦值。
以我們建立的套接字型別是tcp為例,此時struct socket和struct sock的關係如下:
還是繼續剛才sendmsg的過程,由於struct socket的ops指向inet_stream_ops,所以實際呼叫的就是inet_sendmsg
哈哈哈哈哈
索引 索引就像目錄一樣,用來方便查詢,加快查詢速度,但是會增加增刪改的負擔 索引包括b樹索引,主鍵索引,普通索引。事務 把sql語句打包成乙個整體,一但打包成乙個整體不可以執行一半成功,一半失敗,只會出現要麼一起成功,要麼一起失敗 事務有四大特性 原子性,永續性,一致性,隔離性。查詢 select ...
哈哈哈哈哈
據說寫部落格就可以獲得10積分,我來看看是不是這麼簡單就可以了。你好!這是你第一次使用markdown編輯器所展示的歡迎頁。如果你想學習如何使用markdown編輯器,可以仔細閱讀這篇文章,了解一下markdown的基本語法知識。全新的介面設計,將會帶來全新的寫作體驗 在創作中心設定你喜愛的 高亮樣...
哈哈哈哈哈
安裝sha pip install shadowsocks按順序執行下面命令,在 etc目錄下新建資料夾 sha 然後在sha 資料夾下新建檔案 config.json server port 和 password 可以根據自己的要求設定 如果需要同時開多個埠,config.json的內容可以設定如...