C++筆記:select多路復用機制

轉載:http://blog.csdn.net/qdx411324962/article/details/42499535

函數作用:

系統提供select函數來實現多路復用輸入/輸出模型。select系統調用是用來讓我們的程序監視多個文件句柄的狀態變化的。程序會停在select這里等待,直到被監視的文件句柄有一個或多個發生了狀態改變。關于文件句柄,其實就是一個整數,我們最熟悉的句柄是0、1、2三個,0是標準輸入,1是標準輸出,2是標準錯誤輸出。0、1、2是整數表示的,對應的FILE *結構的表示就是stdin、stdout、stderr。

函數原型:

  1. int?select(int?maxfd,fd_set?*rdset,fd_set?*wrset,?\??
  2. ???????????fd_set?*exset,struct?timeval?*timeout);??

參數說明:

參數maxfd是需要監視的最大的文件描述符值+1;rdset,wrset,exset分別對應于需要檢測的可讀文件描述符的集合,可寫文件描述符的集 合及異常文件描述符的集合。struct timeval結構用于描述一段時間長度,如果在這個時間內,需要監視的描述符沒有事件發生則函數返回,返回值為0。

下面的宏提供了處理這三種描述詞組的方式:
FD_CLR(inr fd,fd_set* set);用來清除描述詞組set中相關fd 的位
FD_ISSET(int fd,fd_set *set);用來測試描述詞組set中相關fd 的位是否為真
FD_SET(int fd,fd_set*set);用來設置描述詞組set中相關fd的位
FD_ZERO(fd_set *set);用來清除描述詞組set的全部位

參數timeout為結構timeval,用來設置select()的等待時間,其結構定義如下:

  1. struct?timeval??
  2. {??
  3. ????time_t?tv_sec;//second??
  4. ????time_t?tv_usec;//minisecond??
  5. };??

如果參數timeout設為:

NULL,則表示select()沒有timeout,select將一直被阻塞,直到某個文件描述符上發生了事件。

0:僅檢測描述符集合的狀態,然后立即返回,并不等待外部事件的發生。

特定的時間值:如果在指定的時間段里沒有事件發生,select將超時返回。

函數返回值:

執行成功則返回文件描述詞狀態已改變的個數,如果返回0代表在描述詞狀態改變前已超過timeout時間,沒有返回;當有錯誤發生時則返回-1,錯誤原因存于errno,此時參數readfds,writefds,exceptfds和timeout的值變成不可預測。錯誤值可能為:
EBADF 文件描述詞為無效的或該文件已關閉
EINTR 此調用被信號所中斷
EINVAL 參數n 為負值。
ENOMEM 核心內存不足

常見的程序片段如下:

fs_set readset;
FD_ZERO(&readset);
FD_SET(fd,&readset);
select(fd+1,&readset,NULL,NULL,NULL);
if(FD_ISSET(fd,readset){……}

理解select模型:

理解select模型的關鍵在于理解fd_set,為說明方便,取fd_set長度為1字節,fd_set中的每一bit可以對應一個文件描述符fd。則1字節長的fd_set最大可以對應8個fd。

(1)執行fd_set set; FD_ZERO(&set);則set用位表示是0000,0000。

(2)若fd=5,執行FD_SET(fd,&set);后set變為0001,0000(第5位置為1)

(3)若再加入fd=2,fd=1,則set變為0001,0011

(4)執行select(6,&set,0,0,0)阻塞等待

(5)若fd=1,fd=2上都發生可讀事件,則select返回,此時set變為0000,0011。注意:沒有事件發生的fd=5被清空。

 基于上面的討論,可以輕松得出select模型的特點:

  (1)可監控的文件描述符個數取決與sizeof(fd_set)的值。我這邊服務 器上sizeof(fd_set)=512,每bit表示一個文件描述符,則我服務器上支持的最大文件描述符是512*8=4096。據說可調,另有說雖 然可調,但調整上限受于編譯內核時的變量值。本人對調整fd_set的大小不太感興趣,參考http://www.cppblog.com?/CppExplore/archive/2008/03/21/45061.html中的模型2(1)可以有效突破select可監控的文件描述符上 限。

  (2)將fd加入select監控集的同時,還要再使用一個數據結構array保存放到select監控集中的fd,一是用于再select 返回后,array作為源數據和fd_set進行FD_ISSET判斷。二是select返回后會把以前加入的但并無事件發生的fd清空,則每次開始 select前都要重新從array取得fd逐一加入(FD_ZERO最先),掃描array的同時取得fd最大值maxfd,用于select的第一個 參數。

  (3)可見select模型必須在select前循環array(加fd,取maxfd),select返回后循環array(FD_ISSET判斷是否有時間發生)。

下面給一個偽碼說明基本select模型的服務器模型:

  1. array[slect_len];??
  2.  nSock=0;??
  3.  array[nSock++]=listen_fd;(之前listen?port已綁定并listen)??
  4.  maxfd=listen_fd;??
  5. ??
  6.  while(1){??
  7. ??
  8.   FD_ZERO(&set);??
  9. ??
  10.   foreach?(fd?in?array)??
  11.   {??
  12. ????  fd大于maxfd,則maxfd=fd??
  13. ????  FD_SET(fd,&set)??
  14.   }??
  15. ??
  16.   res=select(maxfd+1,&set,0,0,0);??
  17. ??
  18.   if(FD_ISSET(listen_fd,&set))??
  19.   {??
  20. ????  newfd=accept(listen_fd);??
  21. ????  array[nsock++]=newfd;??
  22. ????  if(--res<=0)?continue;??
  23.   }??
  24. ??
  25.   foreach?下標1開始?(fd?in?array)??
  26.   {??
  27. ????  if(FD_ISSET(fd,&tyle="COLOR:?#ff0000">set))??
  28. ????  執行讀等相關操作??
  29. ????  如果錯誤或者關閉,則要刪除該fd,將array中相應位置和最后一個元素互換就好,nsock減一??
  30. ????  if(--res<=0)?continue;??
  31.   }??
  32. ??
  33.  }??
檢測鍵盤有無輸入,完整的程序如下:

  1. #include<sys/time.h>??
  2. #include<sys/types.h>??
  3. #include<unistd.h>??
  4. #include<string.h>??
  5. #include<stdlib.h>??
  6. #include<stdio.h>??
  7. int?main()??
  8. {??
  9. ????????char?buf[10]="";??
  10. ????????fd_set?rdfds;??
  11. ????????struct?timeval?tv;??
  12. ????????int?ret;??
  13. ????????FD_ZERO(&rdfds);??
  14. ????????FD_SET(0,&rdfds);???//文件描述符0表示stdin鍵盤輸入??
  15. ????????tv.tv_sec?=?3;??
  16. ????????tv.tv_usec?=?500;??
  17. ????????ret?=?select(1,&rdfds,NULL,NULL,&tv);??
  18. ????????if(ret<0)??
  19. ??????????????printf("\n?selcet");??
  20. ????????else?if(ret?==?0)??
  21. ??????????????printf("\n?timeout");??
  22. ????????else??
  23. ??????????????printf("\n?ret?=?%d",ret);??
  24. ??
  25. ????????if(FD_ISSET(1,&rdfds))??//如果有輸入,從stdin中獲取輸入字符??
  26. ????????{??
  27. ??????????????printf("\n?reading");??
  28. ??????????????fread(buf,9,1,stdin);??
  29. ?????????}??
  30. ?????????write(1,buf,strlen(buf));??
  31. ?????????printf("\n?%d?\n",strlen(buf));??
  32. ?????????return?0;??
  33. }??
  34. //執行結果ret?=?1.??

利用Select模型,設計的web服務器:

  1. #include?<stdio.h>??
  2. #include?<stdlib.h>??
  3. #include?<unistd.h>??
  4. #include?<errno.h>??
  5. #include?<string.h>??
  6. #include?<sys/types.h>??
  7. #include?<sys/socket.h>??
  8. #include?<netinet/in.h>??
  9. #include?<arpa/inet.h>??
  10. ??
  11. #define?MYPORT?88960????//?the?port?users?will?be?connecting?to??
  12. ??
  13. #define?BACKLOG?10?????//?how?many?pending?connections?queue?will?hold??
  14. ??
  15. #define?BUF_SIZE?200??
  16. ??
  17. int?fd_A[BACKLOG];????//?accepted?connection?fd??
  18. int?conn_amount;????//?current?connection?amount??
  19. ??
  20. void?showclient()??
  21. {??
  22. ????int?i;??
  23. ????printf("client?amount:?%d\n",?conn_amount);??
  24. ????for?(i?=?0;?i?<?BACKLOG;?i++)?{??
  25. ????????printf("[%d]:%d??",?i,?fd_A[i]);??
  26. ????}??
  27. ????printf("\n\n");??
  28. }??
  29. ??
  30. int?main(void)??
  31. {??
  32. ????int?sock_fd,?new_fd;??//?listen?on?sock_fd,?new?connection?on?new_fd??
  33. ????struct?sockaddr_in?server_addr;????//?server?address?information??
  34. ????struct?sockaddr_in?client_addr;?//?connector's?address?information??
  35. ????socklen_t?sin_size;??
  36. ????int?yes?=?1;??
  37. ????char?buf[BUF_SIZE];??
  38. ????int?ret;??
  39. ????int?i;??
  40. ??
  41. ????if?((sock_fd?=?socket(AF_INET,?SOCK_STREAM,?0))?==?-1)?{??
  42. ????????perror("socket");??
  43. ????????exit(1);??
  44. ????}??
  45. ??
  46. ????if?(setsockopt(sock_fd,?SOL_SOCKET,?SO_REUSEADDR,?&yes,?sizeof(int))?==?-1)?{??
  47. ????????perror("setsockopt");??
  48. ????????exit(1);??
  49. ????}??
  50. ??????
  51. ????server_addr.sin_family?=?AF_INET;?????????//?host?byte?order??
  52. ????server_addr.sin_port?=?htons(MYPORT);?????//?short,?network?byte?order??
  53. ????server_addr.sin_addr.s_addr?=?INADDR_ANY;?//?automatically?fill?with?my?IP??
  54. ????memset(server_addr.sin_zero,?'\0',?sizeof(server_addr.sin_zero));??
  55. ??
  56. ????if?(bind(sock_fd,?(struct?sockaddr?*)&server_addr,?sizeof(server_addr))?==?-1)?{??
  57. ????????perror("bind");??
  58. ????????exit(1);??
  59. ????}??
  60. ??
  61. ????if?(listen(sock_fd,?BACKLOG)?==?-1)?{??
  62. ????????perror("listen");??
  63. ????????exit(1);??
  64. ????}??
  65. ??
  66. ????printf("listen?port?%d\n",?MYPORT);??
  67. ??
  68. ????fd_set?fdsr;??
  69. ????int?maxsock;??
  70. ????struct?timeval?tv;??
  71. ??
  72. ????conn_amount?=?0;??
  73. ????sin_size?=?sizeof(client_addr);??
  74. ????maxsock?=?sock_fd;??
  75. ????while?(1)?{??
  76. ????????//?initialize?file?descriptor?set??
  77. ????????FD_ZERO(&fdsr);??
  78. ????????FD_SET(sock_fd,?&fdsr);??
  79. ??
  80. ????????//?timeout?setting??
  81. ????????tv.tv_sec?=?30;??
  82. ????????tv.tv_usec?=?0;??
  83. ??
  84. ????????//?add?active?connection?to?fd?set??
  85. ????????for?(i?=?0;?i?<?BACKLOG;?i++)?{??
  86. ????????????if?(fd_A[i]?!=?0)?{??
  87. ????????????????FD_SET(fd_A[i],?&fdsr);??
  88. ????????????}??
  89. ????????}??
  90. ??
  91. ????????ret?=?select(maxsock?+?1,?&fdsr,?NULL,?NULL,?&tv);??
  92. ????????if?(ret?<?0)?{??
  93. ????????????perror("select");??
  94. ????????????break;??
  95. ????????}?else?if?(ret?==?0)?{??
  96. ????????????printf("timeout\n");??
  97. ????????????continue;??
  98. ????????}??
  99. ??
  100. ????????//?check?every?fd?in?the?set??
  101. ????????for?(i?=?0;?i?<?conn_amount;?i++)?{??
  102. ????????????if?(FD_ISSET(fd_A[i],?&fdsr))?{??
  103. ????????????????ret?=?recv(fd_A[i],?buf,?sizeof(buf),?0);??
  104. ??????????????????
  105. ????????????????char?str[]?=?"Good,very?nice!\n";??
  106. ??????????????????
  107. ????????????????send(fd_A[i],str,sizeof(str)?+?1,?0);??
  108. ??????????????????
  109. ??????????????????
  110. ????????????????if?(ret?<=?0)?{????????//?client?close??
  111. ????????????????????printf("client[%d]?close\n",?i);??
  112. ????????????????????close(fd_A[i]);??
  113. ????????????????????FD_CLR(fd_A[i],?&fdsr);??
  114. ????????????????????fd_A[i]?=?0;??
  115. ????????????????}?else?{????????//?receive?data??
  116. ????????????????????if?(ret?<?BUF_SIZE)??
  117. ????????????????????????memset(&buf[ret],?'\0',?1);??
  118. ????????????????????printf("client[%d]?send:%s\n",?i,?buf);??
  119. ????????????????}??
  120. ????????????}??
  121. ????????}??
  122. ??
  123. ????????//?check?whether?a?new?connection?comes??
  124. ????????if?(FD_ISSET(sock_fd,?&fdsr))?{??
  125. ????????????new_fd?=?accept(sock_fd,?(struct?sockaddr?*)&client_addr,?&sin_size);??
  126. ????????????if?(new_fd?<=?0)?{??
  127. ????????????????perror("accept");??
  128. ????????????????continue;??
  129. ????????????}??
  130. ??
  131. ????????????//?add?to?fd?queue??
  132. ????????????if?(conn_amount?<?BACKLOG)?{??
  133. ????????????????fd_A[conn_amount++]?=?new_fd;??
  134. ????????????????printf("new?connection?client[%d]?%s:%d\n",?conn_amount,??
  135. ????????????????????????inet_ntoa(client_addr.sin_addr),?ntohs(client_addr.sin_port));??
  136. ????????????????if?(new_fd?>?maxsock)??
  137. ????????????????????maxsock?=?new_fd;??
  138. ????????????}??
  139. ????????????else?{??
  140. ????????????????printf("max?connections?arrive,?exit\n");??
  141. ????????????????send(new_fd,?"bye",?4,?0);??
  142. ????????????????close(new_fd);??
  143. ????????????????break;??
  144. ????????????}??
  145. ????????}??
  146. ????????showclient();??
  147. ????}??
  148. ??
  149. ????//?close?other?connections??
  150. ????for?(i?=?0;?i?<?BACKLOG;?i++)?{??
  151. ????????if?(fd_A[i]?!=?0)?{??
  152. ????????????close(fd_A[i]);??
  153. ????????}??
  154. ????}??
  155. ??
  156. ????exit(0);??
  157. }??
補充部分:

1 基本原理

Resize icon

注:select 原理圖,摘自?IBM iSeries 信息中心

1 數據結構與函數原型

1.1 select

  • 函數原型
       int select(int nfds,fd_set *readset,fd_set *writeset,fd_set* exceptset,struct timeval *timeout);
    
  • 頭文件
    • select位于:
      #include <sys/select.h>
      
    • struct timeval位于:
      #include <sys/time.h>
      
  • 返回值

    返回對應位仍然為1的fd的總數。

  • 參數
    • nfds:第一個參數是:最大的文件描述符值+1;
    • readset:可讀描述符集合;
    • writeset:可寫描述符集合;
    • exceptset:異常描述符;
    • timeout:select 的監聽時長,如果這短時間內所監聽的 socket 沒有事件發生。

1.2 fd_set

1.2.1 清空描述符集合

FD_ZERO(fd_set *)

1.2.2 向描述符集合添加指定描述符

FD_SET(int, fd_set *)

1.2.3 從描述符集合刪除指定描述符

FD_CLR(int, fd_set *)

1.2.4 檢測指定描述符是否在描述符集合中

FD_ISSET(int, fd_set *)

1.2.5 描述符最大數量

#define FD_SETSIZE 1024

1.3 描述符集合

可讀描述符集合中可讀的描述符,為1,其他為0;可寫也類似。異常描述符集合中有異常等待處理的描述符的值為1,其他為0。

1.4 ioctl

  • 函數原型:

      int ioctl(int handle, int cmd,[int *argdx, int argcx]);
    
  • 頭文件:

      #include <sys/ioctl.h>
    
  • 返回值:

    • 0 - 成功
    • 1 - 失敗

2 示例

程序各部分的解釋在注釋中。

#include <sys/socket.h>
#include <string.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>#define TRUE  1
#define FALSE 0int main(int argc, char *argv[])
{int i, len, rc, on = TRUE;int listen_sd, new_sd = 0, max_sd;int desc_ready;char buffer[80];int close_conn, end_server = FALSE;struct sockaddr_in server_addr;struct timeval timeout;struct fd_set master_set, working_set;// Listenlisten_sd = socket(AF_INET, SOCK_STREAM, 0);if (listen_sd < 0){perror("socket() failed");exit(-1);}// Set socket optionsrc = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));if (rc < 0){perror("setsockopt() failed");close(listen_sd);exit(-1);}// Set IO controlrc = ioctl(listen_sd, FIONBIO, (char *) &on);if (rc < 0){perror("ioctl() failed");close(listen_sd);exit(-1);}// Bindmemset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = htonl(INADDR_ANY);server_addr.sin_port = htons(atoi(argv[1]));rc = bind(listen_sd, (struct sockaddr *) &server_addr, sizeof(server_addr));if (rc < 0){perror("bind() failed\n");close(listen_sd);exit(-1);}// Listenrc = listen(listen_sd, 32);if (rc < 0){perror("listen() failed\n");close(listen_sd);exit(-1);}// Intialize sd setFD_ZERO(&master_set);max_sd = listen_sd;FD_SET(listen_sd, &master_set);timeout.tv_sec = 3 * 60;timeout.tv_usec = 0;// Startdo{// Copy master_set into working_setmemcpy(&working_set, &master_set, sizeof(master_set));printf("Waiting on select()...\n");rc = select(max_sd + 1, &working_set, NULL, NULL, &timeout);if (rc < 0){perror("  select() failed\n");break;}if (rc == 0){printf("  select() timed out. End program.\n");break;}desc_ready = rc; // number of sds ready in working_set// Check each sd in working_setfor (i = 0; i <= max_sd && desc_ready > 0; ++i){// Check to see if this sd is readyif (FD_ISSET(i, &working_set)){--desc_ready;// Check to see if this is the listening sdif (i == listen_sd){printf("  Listeing socket is readable\n");do{// Acceptnew_sd = accept(listen_sd, NULL, NULL);// Nothing to be acceptedif (new_sd < 0){// All have been acceptedif (errno != EWOULDBLOCK){perror("  accept() failed\n");end_server = TRUE;}break;}// Insert new_sd into master_setprintf("  New incoming connection - %d\n", new_sd);FD_SET(new_sd, &master_set);if (new_sd > max_sd){max_sd = new_sd;}}while (new_sd != -1);}// This is not the listening sdelse{close_conn = FALSE;printf("  Descriptor %d is avaliable\n", i);do{rc = recv(i, buffer, sizeof(buffer), 0);// Receive data on sd "i", until failure occursif (rc < 0){// Normal failureif (errno != EWOULDBLOCK){perror("  recv() failed\n");close_conn = TRUE;}break;}// The connection has been closed by the clientif (rc == 0){printf("  Connection closed\n");close_conn = TRUE;break;}/* Receiving data succeeded and echo it backthe to client */len = rc;printf("  %d bytes received\n", len);rc = send(i, buffer, len, 0);if (rc < 0){perror("  send() failed");close_conn = TRUE;break;}}while (TRUE);// If unknown failure occuredif (close_conn){// Close the sd and remove it from master_setclose(i);FD_CLR(i, &master_set);// If this is the max sdif (i == max_sd){// Find the max sd in master_set nowwhile (FD_ISSET(max_sd, &master_set) == FALSE){--max_sd;}} // End of if (i == max_sd)} // End of if (close_conn)}}}}while (end_server == FALSE);/* Close each sd in master_set */for (i = 0; i < max_sd; ++i){if (FD_ISSET(i, &master_set)){close(i);}}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384296.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384296.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384296.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

交叉編譯執行應用程序出現:No such file or directory

問題分析 當我在arm板子上執行交叉編譯過的程序的時候發現了這個錯誤。通過百度查詢基本都是缺少32位庫什么的,但是都不能解決問題。 然后我用ll指令&#xff0c;也排除了權限的原因。 我們用ldd指令發現&#xff0c;它不是動態執行的&#xff0c;雖然我們可以使用-static指…

select、poll、epoll 比較

轉載&#xff1a;http://blog.csdn.net/dodo_328/article/details/39081183 1.Selet&#xff1a;本質上是通過設置或者檢查存放fd標志位的數據結構來進行下一步處理。 缺點&#xff1a;1 單個進程可監視的fd數量被限制&#xff0c;因為受描述符集合fd_set限制&#xff0c;fd數量…

C庫函數 File

C庫函數常用的有&#xff1a;fopen, fclose, fread, fwrite, fgets, fputs, fscanf, fprintf, fseek, fgetc, fputc, ftell, feof, flush等&#xff0c; 當使用fopen打開一個文件時通常返回一個文件指針 FILE *fp。FILE類型是一個結構體&#xff0c;包含文件描述符&#xff08;…

Unix 網絡編程(四)- 典型TCP客服服務器程序開發實例及基本套接字API介紹

轉載&#xff1a;http://blog.csdn.net/michael_kong_nju/article/details/43457393 寫在開頭&#xff1a; 在上一節中我們學習了一些基礎的用來支持網絡編程的API&#xff0c;包括“套接字的地址結構”、“字節排序函數”等。這些API幾乎是所有的網絡編程中都會使用的一些&…

C庫函數與系統函數的關系

轉載于:https://www.cnblogs.com/lr1402585172/p/10464933.html

Unix網絡編程(六)高級I/O技術之復用技術 select

轉載&#xff1a;http://blog.csdn.net/michael_kong_nju/article/details/44887411 I/O復用技術 本文將討論網絡編程中的高級I/O復用技術&#xff0c;將從下面幾個方面進行展開&#xff1a; a. 什么是復用技術呢&#xff1f; b. 什么情況下需要使用復用技術呢&#xff1f; c. …

open、read、write、文件類型

open&#xff0c;打開一個文件、創建一個文件或判斷一個文件是否存在。 頭文件&#xff1a;<sys/types.h> <sys/stat.h> <fcntl.h> 重載函數有&#xff1a;int open(const char *pathname, int flags) int open(const char *pathname, int flags, mode_t m…

用模板寫單鏈表 尹成

轉載&#xff1a;http://blog.csdn.net/itcastcpp/article/details/39081953 為了加深對模板的理解&#xff0c;我們今天一起用模板寫一個單鏈表&#xff0c;希望通過這個例子&#xff0c;能夠幫助大家加深對模板的體會&#xff0c;具體如下&#xff1a; SList.hpp內容&#xf…

lseek、stat、access、chmod、strtol、truncate、unlink

lseek&#xff0c;可實現計算文件長度&#xff0c;以及文件擴展。 int ret lseek(fd, 0, SEEK_END); //文件長度printf("file lendth %d\n", ret); int ret lseek(fd, 2000, SEEK_END); //文件拓展2000個byte 在文件末尾偏移2000printf("return va…

inode淺談

索引節點inode&#xff1a;保存的其實是實際的數據的一些信息&#xff0c;這些信息稱為“元數據”(也就是對文件屬性的描述)。例如&#xff1a;文件大小&#xff0c;設備標識符&#xff0c;用戶標識符&#xff0c;用戶組標識符&#xff0c;文件模式&#xff0c;擴展屬性&#x…

Openssl-MD5

http://blog.csdn.net/sunspider107/article/details/7395904 MD5是最常用的一個信息摘要算法&#xff0c;雖然現在慢慢被SHA1算法替代&#xff0c;但還是應用廣泛。 MD5的計算結果是16個字節。 int MD5_Init(MD5_CTX *c); 初始化MD5 Context參數&#xff1b; c: MD5 context; …

opendir、readdir以及使用

opendir&#xff0c;打開一個目錄。 函數原型&#xff1a;DIR *opendir(const char *name) DIR *fopendir(int fd) DIR是一個結構指針&#xff0c;是一個內部結構&#xff0c;保存所打開的目錄信息。函數出錯返回NULL readdir&#xff0c;讀目錄 ,<dirent.h> 函數原型&am…

Linux下C語言使用openssl庫進行MD5校驗

http://blog.csdn.net/cassie_huang/article/details/53212933 作者&#xff1a;無腦仔的小明 出處&#xff1a;http://www.cnblogs.com/wunaozai/ 我們以一個字符串為例&#xff0c;新建一個文件filename.txt&#xff0c;在文件內寫入hello &#xff0c;然后在Linux下可以使…

dup、dup2、fcntl

dup、dup2&#xff0c;復制文件描述符 int dup(int oldfd);  //返回文件描述表中沒有被占用的最小可用的描述符&#xff0c;新舊描述符作用相同 int dup2(int oldfd, int newfd);  //如果new已經被打開&#xff0c;先關閉再拷貝就會指向同一個文件&#xff0c;如果old和new…

進程

創建子進程&#xff1a;fork調用&#xff0c; 一次fork調用返回兩個值&#xff0c;1、返回子進程的pid&#xff08;非負整數&#xff09; 2、返回0 父進程的fork返回子進程的id&#xff0c;子進程的fork返回0&#xff08;表示執行成功&#xff09; 創建單個子進程&#xff1a; …

Ubuntu在vmware虛擬機無法上網的解決方法

http://blog.csdn.net/xueyushenzhou/article/details/50460183 在vmware中安裝Ubuntu之后&#xff0c;我們希望基本的功能如上網、傳輸文件等功能都是可用的&#xff0c;但是經常遇到不能上網的情況。使用筆記本時&#xff0c;我們經常希望能通過無線網卡上網&#xff0c;但是…

exec函數族

fork創建子進程后執行的是和父進程相同的程序&#xff08;但有可能執行不同的代碼分支&#xff09;&#xff0c;子進程往往要調用一種exec函數以執行另一個程序。當進程調用一種exec函數時&#xff0c;該進程的用戶空間代碼和數據完全被新程序替換&#xff0c;從新程序的啟動例…

IO 多路復用之poll總結

http://www.cnblogs.com/Anker/p/3261006.html IO多路復用之poll總結 1、基本知識 poll的機制與select類似&#xff0c;與select在本質上沒有多大差別&#xff0c;管理多個描述符也是進行輪詢&#xff0c;根據描述符的狀態進行處理&#xff0c;但是poll沒有最大文件描述符數量的…

wait、waitpid

父進程調用wait函數可以回收子進程的終止信息&#xff0c;該函數有三個功能&#xff1a;&#xff08;一次wait調用回收一個子進程 回收多個用循環&#xff09; 1、阻塞等待子進程退出 2、回收子進程殘留資源 3、獲取子進程結束狀態&#xff08;退出原因&#xff09; pid_t wait…

C++項目中的extern C {}

http://www.cnblogs.com/skynet/archive/2010/07/10/1774964.html 引言 在用C的項目源碼中&#xff0c;經常會不可避免的會看到下面的代碼&#xff1a; 123456789#ifdef __cplusplusextern "C" {#endif/*...*/#ifdef __cplusplus}#endif它到底有什么用呢&#xff0c;…