<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > linux內(nèi)核中的文件描述符(二)--socket和文件描述符

          linux內(nèi)核中的文件描述符(二)--socket和文件描述符

          作者: 時(shí)間:2016-11-22 來源:網(wǎng)絡(luò) 收藏
          Kernel version:2.6.14

          CPU architecture:ARM920T

          本文引用地址:http://www.ex-cimer.com/article/201611/319998.htm

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

          socket和文件系統(tǒng)緊密相關(guān),我們可以通過文件系統(tǒng)的open、read、write和close等操作socket。下面是一個(gè)簡單的例子。

          [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[]="Hellon";
          19. if(argc!=2)
          20. {
          21. fprintf(stderr,"Usage:%sportnumberan",argv[0]);
          22. exit(1);
          23. }
          24. if((portnumber=atoi(argv[1]))<0)
          25. {
          26. fprintf(stderr,"Usage:%sportnumberan",argv[0]);
          27. exit(1);
          28. }
          29. /*服務(wù)器端開始建立socket描述符*/
          30. if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
          31. {
          32. fprintf(stderr,"Socketerror:%sna",strerror(errno));
          33. exit(1);
          34. }
          35. /*服務(wù)器端填充sockaddr結(jié)構(gòu)*/
          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:%sna",strerror(errno));
          45. exit(1);
          46. }
          47. /*監(jiān)聽sockfd描述符*/
          48. if(listen(sockfd,5)==-1)
          49. {
          50. fprintf(stderr,"Listenerror:%sna",strerror(errno));
          51. exit(1);
          52. }
          53. while(1)
          54. {
          55. /*服務(wù)器阻塞,直到客戶程序建立連接*/
          56. sin_size=sizeof(structsockaddr_in);
          57. if((new_fd=accept(sockfd,(structsockaddr*)(&client_addr),&sin_size))==-1)
          58. {
          59. fprintf(stderr,"Accepterror:%sna",strerror(errno));
          60. exit(1);
          61. }
          62. fprintf(stderr,"Servergetconnectionfrom%sn",
          63. inet_ntoa(client_addr.sin_addr));
          64. if(write(new_fd,hello,strlen(hello))==-1)
          65. {
          66. fprintf(stderr,"WriteError:%sn",strerror(errno));
          67. exit(1);
          68. }
          69. /*這個(gè)通訊已經(jīng)結(jié)束*/
          70. close(new_fd);
          71. /*循環(huán)下一個(gè)*/
          72. }
          73. close(sockfd);
          74. exit(0);
          75. }

          下圖說明了socket和fd是怎樣聯(lián)系起來的。

          下面通過來具體分析一下。sys_socket是socket相關(guān)函數(shù)的總?cè)肟凇?/p>

          [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. }
          當(dāng)應(yīng)用程序使用socket()創(chuàng)建一個(gè)socket時(shí),會(huì)執(zhí)行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);//創(chuàng)建socket
          6. if(retval<0)
          7. gotoout;
          8. retval=sock_map_fd(sock);//分配一個(gè)未使用的文件描述符fd,并將socket和fd建立聯(lián)系
          9. if(retval<0)
          10. gotoout_release;
          11. out:
          12. /*Itmaybealreadyanotherdescriptor8)Notkernelproblem.*/
          13. returnretval;
          14. out_release:
          15. sock_release(sock);
          16. returnretval;
          17. }
          結(jié)構(gòu)體socket的定義如下(includelinuxnet.h):

          [plain]view plaincopy
          print?
          1. structsocket{
          2. socket_statestate;
          3. unsignedlongflags;
          4. structproto_ops*ops;
          5. structfasync_struct*fasync_list;
          6. structfile*file;//通過這個(gè)和文件描述符建立聯(lián)系
          7. structsock*sk;
          8. wait_queue_head_twait;
          9. shorttype;
          10. };
          下面我們?cè)賮砜纯磗ock_map_fd函數(shù)

          [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();//分配一個(gè)未使用的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;//建立聯(lián)系
          32. file->f_op=SOCK_INODE(sock)->i_fop=&socket_file_ops;//socket操作函數(shù),當(dāng)使用文件系統(tǒng)的IO函數(shù)時(shí),其實(shí)使用的是socket的IO函數(shù)
          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. };



          評(píng)論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();