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?
- /****************************************************************************/
- /*简介: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[]=”Hello\n”;
- if(argc!=2)
- {
- fprintf(stderr,”Usage:%sportnumber\a\n”,argv[0]);
- exit(1);
- }
- if((portnumber=atoi(argv[1]))<0)
- {
- fprintf(stderr,”Usage:%sportnumber\a\n”,argv[0]);
- exit(1);
- }
- /*服务器端开端树立socket描述符*/
- if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
- {
- fprintf(stderr,”Socketerror:%s\n\a”,strerror(errno));
- exit(1);
- }
- /*服务器端填充sockaddr结构*/
- 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:%s\n\a”,strerror(errno));
- exit(1);
- }
- /*监听sockfd描述符*/
- if(listen(sockfd,5)==-1)
- {
- fprintf(stderr,”Listenerror:%s\n\a”,strerror(errno));
- exit(1);
- }
- while(1)
- {
- /*服务器堵塞,直到客户程序树立衔接*/
- sin_size=sizeof(structsockaddr_in);
- if((new_fd=accept(sockfd,(structsockaddr*)(&client_addr),&sin_size))==-1)
- {
- fprintf(stderr,”Accepterror:%s\n\a”,strerror(errno));
- exit(1);
- }
- fprintf(stderr,”Servergetconnectionfrom%s\n”,
- inet_ntoa(client_addr.sin_addr));
- if(write(new_fd,hello,strlen(hello))==-1)
- {
- fprintf(stderr,”WriteError:%s\n”,strerror(errno));
- exit(1);
- }
- /*这个通讯现已完毕*/
- close(new_fd);
- /*循环下一个*/
- }
- close(sockfd);
- exit(0);
- }
下图说明晰socket和fd是怎样联络起来的。
下面经过来具体分析一下。sys_socket是socket相关函数的总进口。
[plain]view plaincopy
print?
- 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;
- }
当应用程序运用socket()创立一个socket时,会履行sys_socket,其界说如下
[plain]view plaincopy
print?
- asmlinkagelongsys_socket(intfamily,inttype,intprotocol)
- {
- intretval;
- structsocket*sock;
- retval=sock_create(family,type,protocol,&sock);//创立socket
- if(retval<0)
- gotoout;
- retval=sock_map_fd(sock);//分配一个未运用的文件描述符fd,并将socket和fd树立联络
- if(retval<0)
- gotoout_release;
- out:
- /*Itmaybealreadyanotherdescriptor8)Notkernelproblem.*/
- returnretval;
- out_release:
- sock_release(sock);
- returnretval;
- }
结构体socket的界说如下(include\linux\net.h):
[plain]view plaincopy
print?
- structsocket{
- socket_statestate;
- unsignedlongflags;
- structproto_ops*ops;
- structfasync_struct*fasync_list;
- structfile*file;//经过这个和文件描述符树立联络
- structsock*sk;
- wait_queue_head_twait;
- shorttype;
- };
下面咱们再来看看sock_map_fd函数
[plain]view plaincopy
print?
- 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;//树立联络
- file->f_op=SOCK_INODE(sock)->i_fop=&socket_file_ops;//socket操作函数,当运用文件体系的IO函数时,其实运用的是socket的IO函数
- 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
- };