您的位置 首页 嵌入式

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

Kernelversion:2614CPUarchitecture:ARM920TAuthor:ce123(http:blogcsdnnetce123)socket和文件系统紧密相关,我们可以通过文

Kernel version:2.6.14

CPU architecture:ARM920T

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

socket和文件体系严密相关,咱们能够经过文件体系的open、read、write和close等操作socket。下面是一个简略的比如。

[plain]view plaincopy

print?

  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 plaincopy

print?

  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_sendmsg(a0,(structmsghdr__user*)a1,a[2]);
  75. break;
  76. caseSYS_RECVMSG:
  77. err=sys_recvmsg(a0,(structmsghdr__user*)a1,a[2]);
  78. break;
  79. default:
  80. err=-EINVAL;
  81. break;
  82. }
  83. returnerr;
  84. }/*Itmaybealreadyanotherdescriptor8)Notkernelproblem.*/
  85. returnretval;
  86. out_release:
  87. sock_release(sock);
  88. returnretval;
  89. }

当应用程序运用socket()创立一个socket时,会履行sys_socket,其界说如下

[plain]view plaincopy

print?

  1. asmlinkagelongsys_socket(intfamily,inttype,intprotocol)
  2. {
  3. intretval;
  4. structsocket*sock;
  5. retval=sock_create(family,type,protocol,&sock);//创立socket
  6. if(retval<0)
  7. gotoout;
  8. retval=sock_map_fd(sock);//分配一个未运用的文件描述符fd,并将socket和fd树立联络
  9. if(retval<0)
  10. gotoout_release;
  11. out:
  12. /*Itmaybealreadyanotherdescriptor8)Notkernelproblem.*/
  13. returnretval;
  14. out_release:
  15. sock_release(sock);
  16. returnretval;
  17. }

结构体socket的界说如下(include\linux\net.h):

[plain]view plaincopy

print?

  1. structsocket{
  2. socket_statestate;
  3. unsignedlongflags;
  4. structproto_ops*ops;
  5. structfasync_struct*fasync_list;
  6. structfile*file;//经过这个和文件描述符树立联络
  7. structsock*sk;
  8. wait_queue_head_twait;
  9. shorttype;
  10. };

下面咱们再来看看sock_map_fd函数

[plain]view plaincopy

print?

  1. intsock_map_fd(structsocket*sock)
  2. {
  3. intfd;
  4. structqstrthis;
  5. charname[32];
  6. /*
  7. *Findafiledescriptorsuitableforreturntotheuser.
  8. */
  9. fd=get_unused_fd();//分配一个未运用的fd
  10. if(fd>=0){
  11. structfile*file=get_empty_filp();
  12. if(!file){
  13. put_unused_fd(fd);
  14. fd=-ENFILE;
  15. gotoout;
  16. }
  17. this.len=sprintf(name,”[%lu]”,SOCK_INODE(sock)->i_ino);
  18. this.name=name;
  19. this.hash=SOCK_INODE(sock)->i_ino;
  20. file->f_dentry=d_alloc(sock_mnt->mnt_sb->s_root,&this);
  21. if(!file->f_dentry){
  22. put_filp(file);
  23. put_unused_fd(fd);
  24. fd=-ENOMEM;
  25. gotoout;
  26. }
  27. file->f_dentry->d_op=&sockfs_dentry_operations;
  28. d_add(file->f_dentry,SOCK_INODE(sock));
  29. file->f_vfsmnt=mntget(sock_mnt);
  30. file->f_mapping=file->f_dentry->d_inode->i_mapping;
  31. sock->file=file;//树立联络
  32. file->f_op=SOCK_INODE(sock)->i_fop=&socket_file_ops;//socket操作函数,当运用文件体系的IO函数时,其实运用的是socket的IO函数
  33. file->f_mode=FMODE_READ|FMODE_WRITE;
  34. file->f_flags=O_RDWR;
  35. file->f_pos=0;
  36. file->private_data=sock;
  37. fd_install(fd,file);
  38. }
  39. out:
  40. returnfd;
  41. }
  42. staticstructfile_operationssocket_file_ops={
  43. .owner=THIS_MODULE,
  44. .llseek=no_llseek,
  45. .aio_read=sock_aio_read,
  46. .aio_write=sock_aio_write,
  47. .poll=sock_poll,
  48. .unlocked_ioctl=sock_ioctl,
  49. .mmap=sock_mmap,
  50. .open=sock_no_open,/*specialopencodetodisallowopenvia/proc*/
  51. .release=sock_close,
  52. .fasync=sock_fasync,
  53. .readv=sock_readv,
  54. .writev=sock_writev,
  55. .sendpage=sock_sendpage
  56. };

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/262408.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部