1. 程式人生 > >Linux 核心態 Socket TCP 程式設計

Linux 核心態 Socket TCP 程式設計

1.核心態 socket API

核心態socket程式設計的過程和使用者態下的socket程式設計流程一樣,但是介面不同。Kernel提供了一組核心態的socket API,基本上在使用者態的sockt API在核心中都有對應的API。 在net/socket.c中可以看到如下匯出符號:

  1. EXPORT_SYMBOL(kernel_sendmsg);    
  2. EXPORT_SYMBOL(kernel_recvmsg);    
  3. EXPORT_SYMBOL(sock_create_kern);    
  4. EXPORT_SYMBOL(sock_release);    
  5. EXPORT_SYMBOL(kernel_bind);    
  6. EXPORT_SYMBOL(kernel_listen);    
  7. EXPORT_SYMBOL(kernel_accept);    
  8. EXPORT_SYMBOL(kernel_connect);    
  9. EXPORT_SYMBOL(kernel_getsockname);    
  10. EXPORT_SYMBOL(kernel_getpeername);    
  11. EXPORT_SYMBOL(kernel_getsockopt);    
  12. EXPORT_SYMBOL(kernel_setsockopt);    
  13. EXPORT_SYMBOL(kernel_sendpage);    
  14. EXPORT_SYMBOL(kernel_sock_ioctl);    
  15. EXPORT_SYMBOL(kernel_sock_shutdown);   

下面以兩個核心模組間利用socket進行通訊為例來講述核心態下socket程式設計。

server核心模組功能是:建立套接字,繫結埠,監聽埠,等待client的連線,並接收client發來的資料。

client核心模組功能是:建立套接字,和server建立連線,並向server傳送資料。

2. server模組

  1. /*server.c*/
  2. #include<linux/in.h>
  3. #include<linux/inet.h>
  4. #include<linux/socket.h>
  5. #include<net/sock.h>
  6. #include<linux/init.h>
  7. #include<linux/module.h>
  8. int myserver(void){  
  9.         struct socket *sock,*client_sock;  
  10.         struct sockaddr_in s_addr;  
  11.         unsigned short portnum=0x8888;  
  12.         int ret=0;  
  13.         memset(&s_addr,0,sizeof(s_addr));  
  14.         s_addr.sin_family=AF_INET;  
  15.         s_addr.sin_port=htons(portnum);  
  16.         s_addr.sin_addr.s_addr=htonl(INADDR_ANY);  
  17.         sock=(struct socket *)kmalloc(sizeof(struct socket),GFP_KERNEL);  
  18.         client_sock=(struct socket *)kmalloc(sizeof(struct socket),GFP_KERNEL);  
  19.         /*create a socket*/
  20.         ret=sock_create_kern(AF_INET, SOCK_STREAM,0,&sock);  
  21.         if(ret){  
  22.                 printk("server:socket_create error!\n");  
  23.         }  
  24.         printk("server:socket_create ok!\n");  
  25.         /*bind the socket*/
  26.         ret=sock->ops->bind(sock,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));  
  27.         if(ret<0){  
  28.                 printk("server: bind error\n");  
  29.                 return ret;  
  30.         }  
  31.         printk("server:bind ok!\n");  
  32.         /*listen*/
  33.         ret=sock->ops->listen(sock,10);  
  34.         if(ret<0){  
  35.                 printk("server: listen error\n");  
  36.                 return ret;  
  37.         }  
  38.         printk("server:listen ok!\n");  
  39.         ret=sock->ops->accept(sock,client_sock,10);if(ret<0){  
  40.                 printk("server:accept error!\n");  
  41.                 return ret;  
  42.         }  
  43.         printk("server: accept ok, Connection Established\n");  
  44.         /*kmalloc a receive buffer*/
  45.         char *recvbuf=NULL;  
  46.         recvbuf=kmalloc(1024,GFP_KERNEL);  
  47.         if(recvbuf==NULL){  
  48.                 printk("server: recvbuf kmalloc error!\n");  
  49.                 return -1;  
  50.         }  
  51.         memset(recvbuf, 0, sizeof(recvbuf));  
  52.         /*receive message from client*/
  53.         struct kvec vec;  
  54.         struct msghdr msg;  
  55.         memset(&vec,0,sizeof(vec));  
  56.         memset(&msg,0,sizeof(msg));  
  57.         vec.iov_base=recvbuf;  
  58.         vec.iov_len=1024;  
  59.         ret=kernel_recvmsg(client_sock,&msg,&vec,1,1024,0); /*receive message*/
  60.         printk("receive message:\n %s\n",recvbuf);  
  61.     /*release socket*/
  62.     sock_release(sock);  
  63.         sock_release(client_sock);  
  64.         return ret;  
  65. }  
  66. staticint server_init(void){  
  67.         printk("server init:\n");  
  68.         return (myserver());  
  69. }  
  70. staticvoid server_exit(void){  
  71.         printk("good bye\n");  
  72. }  
  73. module_init(server_init);  
  74. module_exit(server_exit);  
  75. MODULE_LICENSE("GPL");  

3.client模組 
  1. /*client.c*/
  2. #include<linux/in.h>
  3. #include<linux/inet.h>
  4. #include<linux/socket.h>
  5. #include<net/sock.h>
  6. #include<linux/init.h>
  7. #include<linux/module.h>
  8. int myclient(void){  
  9.         struct socket *sock;  
  10.         struct sockaddr_in s_addr;  
  11.         unsigned short portnum=0x8888;  
  12.         int ret=0;  
  13.         memset(&s_addr,0,sizeof(s_addr));  
  14.         s_addr.sin_family=AF_INET;  
  15.         s_addr.sin_port=htons(portnum);  
  16.         s_addr.sin_addr.s_addr=in_aton("192.168.209.134"); /*server ip is 192.168.209.134*/
  17.         sock=(struct socket *)kmalloc(sizeof(struct socket),GFP_KERNEL);  
  18.         /*create a socket*/
  19.         ret=sock_create_kern(AF_INET, SOCK_STREAM,0,&sock);  
  20.         if(ret<0){  
  21.                 printk("client:socket create error!\n");  
  22.                 return ret;  
  23.         }  
  24.         printk("client: socket create ok!\n");  
  25.         /*connect server*/
  26.         ret=sock->ops->connect(sock,(struct sockaddr *)&s_addr, sizeof(s_addr),0);  
  27.         if(ret!=0){  
  28.                 printk("client:connect error!\n");  
  29.                 return ret;  
  30.         }  
  31.         printk("client:connect ok!\n");  
  32.         /*kmalloc sendbuf*/
  33.         char *sendbuf=NULL;  
  34.         sendbuf=kmalloc(1024,GFP_KERNEL);  
  35.         if(sendbuf==NULL){  
  36.                 printk("client: sendbuf kmalloc error!\n");  
  37.                 return -1;  
  38.         }  
  39.         memset(sendbuf,1,1024);          
  40.     struct kvec vec;  
  41.         struct msghdr msg;  
  42.         vec.iov_base=sendbuf;  
  43.         vec.iov_len=1024;  
  44.         memset(&msg,0,sizeof(msg));  
  45.         ret=kernel_sendmsg(sock,&msg,&vec,1,1024); /*send message */
  46.         if(ret<0){  
  47.                 printk("client: kernel_sendmsg error!\n");  
  48.                 return ret;  
  49.         }elseif(ret!=1024){  
  50.                 printk("client: ret!=1024");  
  51.         }  
  52.         printk("client:send ok!\n");  
  53.         return ret;  
  54. }  
  55. staticint client_init(void){  
  56.         printk("client:init\n");  
  57.         return (myclient());  
  58. }  
  59. staticvoid client_exit(void){  
  60.         printk("client exit!\n");  
  61. }  
  62. module_init(client_init);  
  63. module_exit(client_exit);  
  64. MODULE_LICENSE("GPL");