1. 程式人生 > >socket與檔案描述符

socket與檔案描述符

在Linux程式設計時,無論是在操作檔案還是網路操作時都能夠通過檔案描述符來read或者write。之前在沒有接觸C++的時候,不懂面向物件的那套東西。自從學習了C++以及面向物件的一些知識以後突然對Linux這套檔案描述符有了稍微深刻的認識。 怎麼說呢,Linux這一套檔案機制就相當於面向物件裡面的多型,拿到一個檔案描述符都可以進行read或者write。但是具體的read和write卻跟對應檔案描述符的具體實現不同。比如socket的就是走網路,普通檔案的就是走磁碟IO。 下面一張UML類圖大概表現出了Linux檔案描述符的大概意思: 當然,為了將不同的型別的I/O與對應的檔案描述符繫結,則是需要不同的初始化函式的。在C++中有建構函式跟編譯器幫助搞定,在C函式裡只能自己動手豐衣足食了。 普通檔案就通過open函式,指定對應的檔案路徑,作業系統通過路徑能夠找到對應的檔案系統型別,如ext4啊,fat啊等等。 如果是網路呢,就通過socket函式來初始化,socket函式就通過(domain, type, protocol)來找到對應的網路協議棧,比如TCP/IP,UNIX等等。 整個Linux 檔案系統的結構差不多就這個意思,socket跟他繫結也是為了統一介面。 所以網路相關的呼叫,如connect, bind等等,第一步基本上就是通過檔案描述符找到對應的核心socket結構,然後在進行對應的操作。
  1. SYSCALL_DEFINE2(
    listen, int, fd, int, backlog)
  2. {
  3.     struct socket *sock;
  4.     int err, fput_needed;
  5.     int somaxconn;
  6.     /* 通過檔案描述符獲得 kernel socket結構, 並且增加此結構的引用計數 */
  7.     sock = sockfd_lookup_light(fd, &err, &fput_needed);
  8.     if (sock) {
  9.         /* 進行檢測,看看是否滿足系統設計的需求,功能上不重要 */
  10.         somaxconn = sock_net(sock-
    >sk)->core.sysctl_somaxconn;
  11.         if ((unsigned)backlog > somaxconn)
  12.             backlog = somaxconn;
  13.         /* 檢測此呼叫是否安全 */
  14.         err = security_socket_listen(sock, backlog);
  15.         /* 執行具體的listen操作,TCP啊,或者是其他網路協議等等,這個ops是在socket時候繫結的 */
  16.         if (!err)
  17.             err = sock->ops-
    >listen(sock, backlog);
  18.         /* 減少kernel socket的引用計數 */
  19.         fput_light(sock->file, fput_needed);
  20.     }
  21.     return err;
  22. }
上面就是一個典型的呼叫listen的核心操作。 在socket層核心完成的就是一個interface功能,或許也可以叫做橋接模式(bridge pattern)。 這就是我對socket及Linux檔案描述符的理解。