微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > linux内核中的文件描述符(二)--socket和文件描述符

linux内核中的文件描述符(二)--socket和文件描述符

时间:11-22 来源:互联网 点击:
Kernel version:2.6.14

CPU architecture:ARM920T

Author:ce123(http://blog.csdn.net/ce123)

socket和文件系统紧密相关,我们可以通过文件系统的open、read、write和close等操作socket。下面是一个简单的例子。

[plain]view plaincopyprint?

  1. /****************************************************************************/
  2. /*简介:TCPServer示例*/
  3. /****************************************************************************/
  4. #include
  5. #include
  6. #include
  7. #include
  8. #include
  9. #include
  10. #include
  11. #include
  12. intmain(intargc,char*argv[])
  13. {
  14. intsockfd,new_fd;
  15. structsockaddr_inserver_addr;
  16. structsockaddr_inclient_addr;
  17. intsin_size,portnumber;
  18. constcharhello[]="Hello\n";
  19. if(argc!=2)
  20. {
  21. fprintf(stderr,"Usage:%sportnumber\a\n",argv[0]);
  22. exit(1);
  23. }
  24. if((portnumber=atoi(argv[1]))<0)
  25. {
  26. fprintf(stderr,"Usage:%sportnumber\a\n",argv[0]);
  27. exit(1);
  28. }
  29. /*服务器端开始建立socket描述符*/
  30. if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
  31. {
  32. fprintf(stderr,"Socketerror:%s\n\a",strerror(errno));
  33. exit(1);
  34. }
  35. /*服务器端填充sockaddr结构*/
  36. bzero(&server_addr,sizeof(structsockaddr_in));
  37. server_addr.sin_family=AF_INET;
  38. server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
  39. server_addr.sin_port=htons(portnumber);
  40. /*捆绑sockfd描述符*/
  41. if(bind(sockfd,(structsockaddr*)(&server_addr),sizeof(structsockaddr))==
  42. -1)
  43. {
  44. fprintf(stderr,"Binderror:%s\n\a",strerror(errno));
  45. exit(1);
  46. }
  47. /*监听sockfd描述符*/
  48. if(listen(sockfd,5)==-1)
  49. {
  50. fprintf(stderr,"Listenerror:%s\n\a",strerror(errno));
  51. exit(1);
  52. }
  53. while(1)
  54. {
  55. /*服务器阻塞,直到客户程序建立连接*/
  56. sin_size=sizeof(structsockaddr_in);
  57. if((new_fd=accept(sockfd,(structsockaddr*)(&client_addr),&sin_size))==-1)
  58. {
  59. fprintf(stderr,"Accepterror:%s\n\a",strerror(errno));
  60. exit(1);
  61. }
  62. fprintf(stderr,"Servergetconnectionfrom%s\n",
  63. inet_ntoa(client_addr.sin_addr));
  64. if(write(new_fd,hello,strlen(hello))==-1)
  65. {
  66. fprintf(stderr,"WriteError:%s\n",strerror(errno));
  67. exit(1);
  68. }
  69. /*这个通讯已经结束*/
  70. close(new_fd);
  71. /*循环下一个*/
  72. }
  73. close(sockfd);
  74. exit(0);
  75. }

下图说明了socket和fd是怎样联系起来的。

下面通过来具体分析一下。sys_socket是socket相关函数的总入口。

[plain]view plaincopyprint?

  1. net/socket.c
  2. /*
  3. *Systemcallvectors.
  4. *
  5. *Argumentcheckingcleanedup.Saved20%insize.
  6. *Thisfunctiondoesntneedtosetthekernellockbecause
  7. *itissetbythecallees.
  8. */
  9. asmlinkagelongsys_socketcall(intcall,unsignedlong__user*args)
  10. {
  11. unsignedlonga[6];
  12. unsignedlonga0,a1;
  13. interr;
  14. if(call<1||call>SYS_RECVMSG)
  15. return-EINVAL;
  16. /*copy_from_usershouldbeSMPsafe.*/
  17. if(copy_from_user(a,args,nargs[call]))
  18. return-EFAULT;
  19. err=audit_socketcall(nargs[call]/sizeof(unsignedlong),a);
  20. if(err)
  21. returnerr;
  22. a0=a[0];
  23. a1=a[1];
  24. switch(call)
  25. {
  26. caseSYS_SOCKET:
  27. err=sys_socket(a0,a1,a[2]);
  28. break;
  29. caseSYS_BIND:
  30. err=sys_bind(a0,(structsockaddr__user*)a1,a[2]);
  31. break;
  32. caseSYS_CONNECT:
  33. err=sys_connect(a0,(structsockaddr__user*)a1,a[2]);
  34. break;
  35. caseSYS_LISTEN:
  36. err=sys_listen(a0,a1);
  37. break;
  38. caseSYS_ACCEPT:
  39. err=sys_accept(a0,(structsockaddr__user*)a1,(int__user*)a[2]);
  40. break;
  41. caseSYS_GETSOCKNAME:
  42. err=sys_getsockname(a0,(structsockaddr__user*)a1,(int__user*)a[2]);
  43. break;
  44. caseSYS_GETPEERNAME:
  45. err=sys_getpeername(a0,(structsockaddr__user*)a1,(int__user*)a[2]);
  46. break;
  47. caseSYS_SOCKETPAIR:
  48. err=sys_socketpair(a0,a1,a[2],(int__user*)a[3]);
  49. break;
  50. caseSYS_SEND:
  51. err=sys_send(a0,(void__user*)a1,a[2],a[3]);
  52. break;
  53. caseSYS_SENDTO:
  54. err=sys_sendto(a0,(void__user*)a1,a[2],a[3],
  55. (structsockaddr__user*)a[4],a[5]);
  56. break;
  57. caseSYS_RECV:
  58. err=sys_recv(a0,(void__user*)a1,a[2],a[3]);
  59. break;
  60. caseSYS_RECVFROM:
  61. err=sys_recvfrom(a0,(void__user*)a1,a[2],a[3],
  62. (structsockaddr__user*)a[4],(int__user*)a[5]);
  63. break;
  64. caseSYS_SHUTDOWN:
  65. err=sys_shutdown(a0,a1);
  66. break;
  67. caseSYS_SETSOCKOPT:
  68. err=sys_setsockopt(a0,a1,a[2],(char__user*)a[3],a[4]);
  69. break;
  70. caseSYS_GETSOCKOPT:
  71. err=sys_getsockopt(a0,a1,a[2],(char__user*)a[3],(int__user*)a[4]);
  72. break;
  73. caseSYS_SENDMSG:
  74. err=sys_sen

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top