linux內(nèi)核中的文件描述符(二)--socket和文件描述符
CPU architecture:ARM920T
本文引用地址:http://m.butianyuan.cn/article/201611/319998.htmAuthor:ce123(http://blog.csdn.net/ce123)
socket和文件系統(tǒng)緊密相關(guān),我們可以通過文件系統(tǒng)的open、read、write和close等操作socket。下面是一個簡單的例子。
[plain]view plaincopyprint?
- /****************************************************************************/
- /*簡介:TCPServer示例*/
- /****************************************************************************/
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- intmain(intargc,char*argv[])
- {
- intsockfd,new_fd;
- structsockaddr_inserver_addr;
- structsockaddr_inclient_addr;
- intsin_size,portnumber;
- constcharhello[]="Hellon";
- if(argc!=2)
- {
- fprintf(stderr,"Usage:%sportnumberan",argv[0]);
- exit(1);
- }
- if((portnumber=atoi(argv[1]))<0)
- {
- fprintf(stderr,"Usage:%sportnumberan",argv[0]);
- exit(1);
- }
- /*服務(wù)器端開始建立socket描述符*/
- if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
- {
- fprintf(stderr,"Socketerror:%sna",strerror(errno));
- exit(1);
- }
- /*服務(wù)器端填充sockaddr結(jié)構(gòu)*/
- bzero(&server_addr,sizeof(structsockaddr_in));
- server_addr.sin_family=AF_INET;
- server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
- server_addr.sin_port=htons(portnumber);
- /*捆綁sockfd描述符*/
- if(bind(sockfd,(structsockaddr*)(&server_addr),sizeof(structsockaddr))==
- -1)
- {
- fprintf(stderr,"Binderror:%sna",strerror(errno));
- exit(1);
- }
- /*監(jiān)聽sockfd描述符*/
- if(listen(sockfd,5)==-1)
- {
- fprintf(stderr,"Listenerror:%sna",strerror(errno));
- exit(1);
- }
- while(1)
- {
- /*服務(wù)器阻塞,直到客戶程序建立連接*/
- sin_size=sizeof(structsockaddr_in);
- if((new_fd=accept(sockfd,(structsockaddr*)(&client_addr),&sin_size))==-1)
- {
- fprintf(stderr,"Accepterror:%sna",strerror(errno));
- exit(1);
- }
- fprintf(stderr,"Servergetconnectionfrom%sn",
- inet_ntoa(client_addr.sin_addr));
- if(write(new_fd,hello,strlen(hello))==-1)
- {
- fprintf(stderr,"WriteError:%sn",strerror(errno));
- exit(1);
- }
- /*這個通訊已經(jīng)結(jié)束*/
- close(new_fd);
- /*循環(huán)下一個*/
- }
- close(sockfd);
- exit(0);
- }
下圖說明了socket和fd是怎樣聯(lián)系起來的。
下面通過來具體分析一下。sys_socket是socket相關(guān)函數(shù)的總?cè)肟凇?/p>
[plain]view plaincopyprint?
- net/socket.c
- /*
- *Systemcallvectors.
- *
- *Argumentcheckingcleanedup.Saved20%insize.
- *Thisfunctiondoesntneedtosetthekernellockbecause
- *itissetbythecallees.
- */
- asmlinkagelongsys_socketcall(intcall,unsignedlong__user*args)
- {
- unsignedlonga[6];
- unsignedlonga0,a1;
- interr;
- if(call<1||call>SYS_RECVMSG)
- return-EINVAL;
- /*copy_from_usershouldbeSMPsafe.*/
- if(copy_from_user(a,args,nargs[call]))
- return-EFAULT;
- err=audit_socketcall(nargs[call]/sizeof(unsignedlong),a);
- if(err)
- returnerr;
- a0=a[0];
- a1=a[1];
- switch(call)
- {
- caseSYS_SOCKET:
- err=sys_socket(a0,a1,a[2]);
- break;
- caseSYS_BIND:
- err=sys_bind(a0,(structsockaddr__user*)a1,a[2]);
- break;
- caseSYS_CONNECT:
- err=sys_connect(a0,(structsockaddr__user*)a1,a[2]);
- break;
- caseSYS_LISTEN:
- err=sys_listen(a0,a1);
- break;
- caseSYS_ACCEPT:
- err=sys_accept(a0,(structsockaddr__user*)a1,(int__user*)a[2]);
- break;
- caseSYS_GETSOCKNAME:
- err=sys_getsockname(a0,(structsockaddr__user*)a1,(int__user*)a[2]);
- break;
- caseSYS_GETPEERNAME:
- err=sys_getpeername(a0,(structsockaddr__user*)a1,(int__user*)a[2]);
- break;
- caseSYS_SOCKETPAIR:
- err=sys_socketpair(a0,a1,a[2],(int__user*)a[3]);
- break;
- caseSYS_SEND:
- err=sys_send(a0,(void__user*)a1,a[2],a[3]);
- break;
- caseSYS_SENDTO:
- err=sys_sendto(a0,(void__user*)a1,a[2],a[3],
- (structsockaddr__user*)a[4],a[5]);
- break;
- caseSYS_RECV:
- err=sys_recv(a0,(void__user*)a1,a[2],a[3]);
- break;
- caseSYS_RECVFROM:
- err=sys_recvfrom(a0,(void__user*)a1,a[2],a[3],
- (structsockaddr__user*)a[4],(int__user*)a[5]);
- break;
- caseSYS_SHUTDOWN:
- err=sys_shutdown(a0,a1);
- break;
- caseSYS_SETSOCKOPT:
- err=sys_setsockopt(a0,a1,a[2],(char__user*)a[3],a[4]);
- break;
- caseSYS_GETSOCKOPT:
- err=sys_getsockopt(a0,a1,a[2],(char__user*)a[3],(int__user*)a[4]);
- break;
- caseSYS_SENDMSG:
- err=sys_sendmsg(a0,(structmsghdr__user*)a1,a[2]);
- break;
- caseSYS_RECVMSG:
- err=sys_recvmsg(a0,(structmsghdr__user*)a1,a[2]);
- break;
- default:
- err=-EINVAL;
- break;
- }
- returnerr;
- }/*Itmaybealreadyanotherdescriptor8)Notkernelproblem.*/
- returnretval;
- out_release:
- sock_release(sock);
- returnretval;
- }
[plain]view plaincopyprint?
- asmlinkagelongsys_socket(intfamily,inttype,intprotocol)
- {
- intretval;
- structsocket*sock;
- retval=sock_create(family,type,protocol,&sock);//創(chuàng)建socket
- if(retval<0)
- gotoout;
- retval=sock_map_fd(sock);//分配一個未使用的文件描述符fd,并將socket和fd建立聯(lián)系
- if(retval<0)
- gotoout_release;
- out:
- /*Itmaybealreadyanotherdescriptor8)Notkernelproblem.*/
- returnretval;
- out_release:
- sock_release(sock);
- returnretval;
- }
[plain]view plaincopyprint?
- structsocket{
- socket_statestate;
- unsignedlongflags;
- structproto_ops*ops;
- structfasync_struct*fasync_list;
- structfile*file;//通過這個和文件描述符建立聯(lián)系
- structsock*sk;
- wait_queue_head_twait;
- shorttype;
- };
[plain]view plaincopyprint?
- intsock_map_fd(structsocket*sock)
- {
- intfd;
- structqstrthis;
- charname[32];
- /*
- *Findafiledescriptorsuitableforreturntotheuser.
- */
- fd=get_unused_fd();//分配一個未使用的fd
- if(fd>=0){
- structfile*file=get_empty_filp();
- if(!file){
- put_unused_fd(fd);
- fd=-ENFILE;
- gotoout;
- }
- this.len=sprintf(name,"[%lu]",SOCK_INODE(sock)->i_ino);
- this.name=name;
- this.hash=SOCK_INODE(sock)->i_ino;
- file->f_dentry=d_alloc(sock_mnt->mnt_sb->s_root,&this);
- if(!file->f_dentry){
- put_filp(file);
- put_unused_fd(fd);
- fd=-ENOMEM;
- gotoout;
- }
- file->f_dentry->d_op=&sockfs_dentry_operations;
- d_add(file->f_dentry,SOCK_INODE(sock));
- file->f_vfsmnt=mntget(sock_mnt);
- file->f_mapping=file->f_dentry->d_inode->i_mapping;
- sock->file=file;//建立聯(lián)系
- file->f_op=SOCK_INODE(sock)->i_fop=&socket_file_ops;//socket操作函數(shù),當(dāng)使用文件系統(tǒng)的IO函數(shù)時,其實使用的是socket的IO函數(shù)
- file->f_mode=FMODE_READ|FMODE_WRITE;
- file->f_flags=O_RDWR;
- file->f_pos=0;
- file->private_data=sock;
- fd_install(fd,file);
- }
- out:
- returnfd;
- }
- staticstructfile_operationssocket_file_ops={
- .owner=THIS_MODULE,
- .llseek=no_llseek,
- .aio_read=sock_aio_read,
- .aio_write=sock_aio_write,
- .poll=sock_poll,
- .unlocked_ioctl=sock_ioctl,
- .mmap=sock_mmap,
- .open=sock_no_open,/*specialopencodetodisallowopenvia/proc*/
- .release=sock_close,
- .fasync=sock_fasync,
- .readv=sock_readv,
- .writev=sock_writev,
- .sendpage=sock_sendpage
- };
評論