精华内容
下载资源
问答
  • netlink编程,内核态和用户态编程。netlink编程,内核态和用户态编程
  • Linux 内核态 Socket 编程

    千次阅读 2015-04-01 16:18:49
    Linux 内核态 Socket 编程 分类: Socket2013-11-27 15:48 909人阅读 评论(0) 收藏 举报 1.内核态 socket API 内核态socket编程的过程和用户态下的socket编程流程一样,但是接口不同。Kernel...
     

    Linux 内核态 Socket 编程

    分类: Socket   909人阅读  评论(0)  收藏  举报

    1.内核态 socket API

    内核态socket编程的过程和用户态下的socket编程流程一样,但是接口不同。Kernel提供了一组内核态的socket API,基本上在用户态的sockt API在内核中都有对应的API。 在net/socket.c中可以看到如下导出符号:

    [cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
    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模块

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

    3.client模块

    [cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
    1. /*client.c*/  
    2. #include<linux/in.h>  
    3. #include<linux/inet.h>  
    4. #include<linux/socket.h>  
    5. #include<net/sock.h>  
    6.   
    7. #include<linux/init.h>  
    8. #include<linux/module.h>  
    9.   
    10. int myclient(void){  
    11.         struct socket *sock;  
    12.         struct sockaddr_in s_addr;  
    13.         unsigned short portnum=0x8888;  
    14.         int ret=0;  
    15.   
    16.         memset(&s_addr,0,sizeof(s_addr));  
    17.         s_addr.sin_family=AF_INET;  
    18.         s_addr.sin_port=htons(portnum);  
    19.        
    20.         s_addr.sin_addr.s_addr=in_aton("192.168.209.134"); /*server ip is 192.168.209.134*/  
    21.         sock=(struct socket *)kmalloc(sizeof(struct socket),GFP_KERNEL);  
    22.   
    23.         /*create a socket*/  
    24.         ret=sock_create_kern(AF_INET, SOCK_STREAM,0,&sock);  
    25.         if(ret<0){  
    26.                 printk("client:socket create error!\n");  
    27.                 return ret;  
    28.         }  
    29.         printk("client: socket create ok!\n");  
    30.   
    31.         /*connect server*/  
    32.         ret=sock->ops->connect(sock,(struct sockaddr *)&s_addr, sizeof(s_addr),0);  
    33.         if(ret!=0){  
    34.                 printk("client:connect error!\n");  
    35.                 return ret;  
    36.         }  
    37.         printk("client:connect ok!\n");  
    38.   
    39.         /*kmalloc sendbuf*/  
    40.         char *sendbuf=NULL;  
    41.         sendbuf=kmalloc(1024,GFP_KERNEL);  
    42.         if(sendbuf==NULL){  
    43.                 printk("client: sendbuf kmalloc error!\n");  
    44.                 return -1;  
    45.         }  
    46.         memset(sendbuf,1,1024);          
    47.           
    48.     struct kvec vec;  
    49.         struct msghdr msg;  
    50.   
    51.         vec.iov_base=sendbuf;  
    52.         vec.iov_len=1024;  
    53.   
    54.         memset(&msg,0,sizeof(msg));  
    55.   
    56.         ret=kernel_sendmsg(sock,&msg,&vec,1,1024); /*send message */  
    57.         if(ret<0){  
    58.                 printk("client: kernel_sendmsg error!\n");  
    59.                 return ret;  
    60.         }else if(ret!=1024){  
    61.                 printk("client: ret!=1024");  
    62.         }  
    63.         printk("client:send ok!\n");  
    64.   
    65.         return ret;  
    66. }  
    67.   
    68. static int client_init(void){  
    69.         printk("client:init\n");  
    70.         return (myclient());  
    71. }  
    72.   
    73. static void client_exit(void){  
    74.         printk("client exit!\n");  
    75. }  
    76.   
    77. module_init(client_init);  
    78. module_exit(client_exit);  
    79. MODULE_LICENSE("GPL"); 
    展开全文
  • 内核态 Socket TCP编程

    2017-04-18 17:19:35
    内核态socket编程的过程和用户态下的socket编程流程一样,但是接口不同。Kernel提供了一组内核态的socket API,基本上在用户态的sockt API在内核中都有对应的API。 在net/socket.c中可以看到如下导出符号: ...

    1.内核态 socket API

    内核态socket编程的过程和用户态下的socket编程流程一样,但是接口不同。Kernel提供了一组内核态的socket API,基本上在用户态的sockt API在内核中都有对应的API。 在net/socket.c中可以看到如下导出符号:

    [cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
    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模块

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

    3.client模块

    [cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
    1. /*client.c*/  
    2. #include<linux/in.h>  
    3. #include<linux/inet.h>  
    4. #include<linux/socket.h>  
    5. #include<net/sock.h>  
    6.   
    7. #include<linux/init.h>  
    8. #include<linux/module.h>  
    9.   
    10. int myclient(void){  
    11.         struct socket *sock;  
    12.         struct sockaddr_in s_addr;  
    13.         unsigned short portnum=0x8888;  
    14.         int ret=0;  
    15.   
    16.         memset(&s_addr,0,sizeof(s_addr));  
    17.         s_addr.sin_family=AF_INET;  
    18.         s_addr.sin_port=htons(portnum);  
    19.        
    20.         s_addr.sin_addr.s_addr=in_aton("192.168.209.134"); /*server ip is 192.168.209.134*/  
    21.         sock=(struct socket *)kmalloc(sizeof(struct socket),GFP_KERNEL);  
    22.   
    23.         /*create a socket*/  
    24.         ret=sock_create_kern(AF_INET, SOCK_STREAM,0,&sock);  
    25.         if(ret<0){  
    26.                 printk("client:socket create error!\n");  
    27.                 return ret;  
    28.         }  
    29.         printk("client: socket create ok!\n");  
    30.   
    31.         /*connect server*/  
    32.         ret=sock->ops->connect(sock,(struct sockaddr *)&s_addr, sizeof(s_addr),0);  
    33.         if(ret!=0){  
    34.                 printk("client:connect error!\n");  
    35.                 return ret;  
    36.         }  
    37.         printk("client:connect ok!\n");  
    38.   
    39.         /*kmalloc sendbuf*/  
    40.         char *sendbuf=NULL;  
    41.         sendbuf=kmalloc(1024,GFP_KERNEL);  
    42.         if(sendbuf==NULL){  
    43.                 printk("client: sendbuf kmalloc error!\n");  
    44.                 return -1;  
    45.         }  
    46.         memset(sendbuf,1,1024);          
    47.           
    48.     struct kvec vec;  
    49.         struct msghdr msg;  
    50.   
    51.         vec.iov_base=sendbuf;  
    52.         vec.iov_len=1024;  
    53.   
    54.         memset(&msg,0,sizeof(msg));  
    55.   
    56.         ret=kernel_sendmsg(sock,&msg,&vec,1,1024); /*send message */  
    57.         if(ret<0){  
    58.                 printk("client: kernel_sendmsg error!\n");  
    59.                 return ret;  
    60.         }else if(ret!=1024){  
    61.                 printk("client: ret!=1024");  
    62.         }  
    63.         printk("client:send ok!\n");  
    64.   
    65.         return ret;  
    66. }  
    67.   
    68. static int client_init(void){  
    69.         printk("client:init\n");  
    70.         return (myclient());  
    71. }  
    72.   
    73. static void client_exit(void){  
    74.         printk("client exit!\n");  
    75. }  
    76.   
    77. module_init(client_init);  
    78. module_exit(client_exit);  
    79. MODULE_LICENSE("GPL"); 
    展开全文
  • 内核态socket编程

    千次阅读 2015-04-01 17:12:10
    内核态的socket编程 分类: 嵌入式开发2013-06-17 15:32 794人阅读 评论(0) 收藏 举报 记不清从哪个kernel版本开始,内核态就不能直接使用系统调用了。当然,socket的系统调用也不能用了。不过好在kernel...
     

    内核态的socket编程

    分类: 嵌入式开发   794人阅读   评论(0)   收藏   举报

    记不清从哪个kernel版本开始,内核态就不能直接使用系统调用了。当然,socket的系统调用也不能用了。不过好在kernel提供了一组内核态的socket 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的API,在内核态都有对应的API。


    下面是一个项目中的代码,socket操作我加了注视。不用去关心代码功能,只要看一下socket部分的操作即可,非常简单。

    1. #include <linux/socket.h>  
    2. #include <linux/net.h>  
    3. #include <linux/in.h>  
    4.   
    5. struct fsg_common{  
    6. ....  
    7.         struct socket *encrypt_sock;   
    8.         struct msghdr encrypt_msg;  
    9.         struct sockaddr_in encrypt_servaddr;  
    10.         struct data_pkt *encrypt_pkt;  
    11. }  
    12.   
    13. static int encrypt_socket_init(struct fsg_common *common)  
    14. {  
    15.     struct socket *sock;  
    16.     int ret;  
    17.     char *dst_addr = "111.111.111.111";  
    18.     /* init servaddr */  
    19.     memset(&common->encrypt_servaddr, 0, sizeof(common->encrypt_servaddr));  
    20.     common->encrypt_servaddr.sin_family = AF_INET;  
    21.     common->encrypt_servaddr.sin_port = htons(9999);  
    22.       
    23.     //kernel态的IP地址转换函数,有两个函数in4_pton和in6_pton,分别用于IPv4和IPv6  
    24.     in4_pton(dst_addr, strlen(dst_addr), (u8*)&common->encrypt_servaddr.sin_addr, '\0', NULL);  
    25.       
    26.     //内核态udp通信地址使用struct msghdr封装  
    27.     common->encrypt_msg.msg_name = &common->encrypt_servaddr;  
    28.     common->encrypt_msg.msg_namelen = sizeof(common->encrypt_servaddr);  
    29.   
    30.     //创建套接字,类似socket()函数,返回的sock指针就是后面数据传递用的套接字了  
    31.     ret = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);  
    32.     if (ret < 0 || NULL == sock) {  
    33.         ERROR(common, "init encrypt board socket fail\n");  
    34.         return ret;  
    35.     }  
    36.     common->encrypt_sock = sock;  
    37.   
    38.     common->encrypt_pkt = kmalloc(sizeof(struct data_pkt), GFP_KERNEL);  
    39.     if (NULL == common->encrypt_pkt)  
    40.         return -1;  
    41.   
    42.     return 0;  
    43. }  
    44.   
    45. static void encrypt_socket_close(struct fsg_common *common)  
    46. {  
    47.     //关闭套接字,类似用户态的close()函数  
    48.     sock_release(common->encrypt_sock);  
    49.     common->encrypt_sock = NULL;  
    50. }  
    51.   
    52. static int encrypt_data(struct fsg_common *common, u8* data, unsigned int size, loff_t offset)  
    53. {  
    54.     struct socket *sock = common->encrypt_sock;   
    55.     struct data_pkt *pkt = common->encrypt_pkt;  
    56.     struct sockaddr *pservaddr = (struct sockaddr *)&common->encrypt_servaddr;  
    57.     int servlen = sizeof(common->encrypt_servaddr);  
    58.   
    59.     if (unlikely(NULL == sock || NULL == pkt || NULL == pservaddr))  
    60.         return -1;  
    61.   
    62.     memset(pkt, 0, sizeof(struct data_pkt));  
    63.     unsigned int copied_size = 0;  
    64.     struct kvec vec;  
    65.     struct msghdr msg;  
    66.     memset(&msg, 0, sizeof(msg));  
    67.   
    68.     while (copied_size < size) {  
    69.         pkt->res=0xffffffff;  
    70.         pkt->file_offset = offset;   
    71.         memcpy(pkt->data, data + copied_size, SECTOR_SIZE);  
    72.   
    73.         //配置udp发送数据地址及长度  
    74.         vec.iov_base = (void *)pkt;  
    75.         vec.iov_len = sizeof(struct data_pkt);  
    76.         ret = kernel_sendmsg(sock, &common->encrypt_msg, &vec, 1, sizeof(struct data_pkt));  
    77.         printk("send data(return :%d):\n", ret);  
    78.   
    79.         //接收udp报文  
    80.         ret = kernel_recvmsg(sock, &msg, &vec, 1, sizeof(struct data_pkt), 0);  
    81.         printk("recv data(return :%d):\n", ret);  
    82.         memcpy(data+copied_size, pkt->data, 512);  
    83.         copied_size += 512;  
    84.     }     
    85.   
    86.     return 0;  
    87. }
    展开全文
  • linux内核编程-内核态文件操作

    千次阅读 2018-04-01 21:39:30
    一、文件打开函数struct file *filp_open(const char *filename, int flags, umode_t mode)定义在:fs/open.c头文件:&lt;linux/fs.h&...在内核态如果O_CREAT标志指定mode参数指定权限,否则为02...

    一、文件打开函数

    struct file *filp_open(const char *filename, int flags, umode_t mode)

    定义在:fs/open.c

    头文件:<linux/fs.h>

    详解:

    1.在用户态open函数是个变参函数,umode_t mode参数只有在O_CREAT标志指定时才出现。在内核态如果O_CREAT标志指定mode参数指定权限,否则为0

    2.filename参数和flags和用户态一样,指定文件路径和打开标志

    3.返回值,如果成功返回struct file 类型变量。失败时要注意,它失败了返回的不是NULL,而是一个错误码。所以对于返回值的判断应该用下面的方式

    if(IS_ERR(file))

    IS_ERR(file)为真打开失败,为假打开成功。linux内核为什么这么设计,可以参考https://blog.csdn.net/yaozhenguo2006/article/details/7967547

    二、读写函数

    用户态读写文件只提供了一种方法read、write。而在内核态读写文件可以有好几种,接下来分别看看这几张方法,并对其进行一下比较

    方法1:当打开文件成功后,返回了struct file类型变量,此变量中包含了struct file_operations文件操作函数集所以可以如下操作

    file->f_op->read(file,buf,size,&pos);

    file->f_op->write(file,buf,size,&pos);

    方法二:使用vfs_read、vfs_write函数,他是内核对file->f_op->read、write的封装。定义在fs/read_write.c,头文件<linux/fs.h>

    ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos);

    ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos);

    注意:以上两种方法中,函数对buf参数进行了__user限定,内核会对buf地址进行检测。也就是说buf的地址必须是用户空间的地址,如果在内核中使用会返回-EFAULT错误。所以在调用以上两种方法中的函数时可以使用set_fs()、get_fs()来解决。

    使用方法:

    mm_segmet_t old_fs;

    .........

    old_fs = get_fs();

    set_fs(get_ds());

    vfs_read(file,buf,size,&pos);

    set_fs(old_fs);

    进行了set_fs设置后,内核就不在对内存地址进行检测。关于set_fs()可以参考:https://www.cnblogs.com/soul-stone/p/6367696.html

    方法三:先说读函数,可以使用kernel_read函数,这个函数其实就是加入了set_fs()、get_fs()函数。在4.14前

    定义为int kernel_read(struct file *file, loff_t offset, char *addr, unsigned long conut),定义在fs/exec.c中,头文件<linux/fs.h>

    在4.14及之后的版本中定义为ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos),定义在fs/read_write.c中,头文件<linux/fs.h>

    接下来再说写函数,__kernel_write和kernel_write函数,在3.9之前没有这两个函数,3.9版本中定义了__kernel_write函数,但是没有导出符合,模块编程中也调用不了,我们可以仿照此函数编写一个自己的kern_write函数。在3.18版本后__kernel_write函数导出了。其定义:ssize_t __kernle_write(struct file *file, const char *buf, size_t count, loff_t *pos),定义在fs/read_write.c中,头文件<linux/fs.h>。kernel_write函数在4.14版本开始定义和__kernel_write参数一样,且导出了此符合。

    三、文件关闭

    int filp_close(struct file *file, fl_owner_t id)。定义在fs/open.c,头文件<linux/fs>

    用法:一般为 filp_close(file,NULL);


    展开全文
  • 内核态 Socket UDP编程

    千次阅读 2017-04-18 17:24:56
    记不清从哪个kernel版本开始,内核态就不能直接使用系统调用了。当然,socket的系统调用也不能用了。不过好在kernel提供了一组内核态的socket API。在net/socket.c文件中,可以看到这么几个导出符号: [cpp]...
  • Linux 内核态 Socket TCP 编程

    千次阅读 2016-04-22 10:57:12
    标签: linux c++ socket编程 c++ sock linux下socket c++  转自: ... ...1.内核态 socket API ...内核态socket编程的过程和用户态下的socket编程流程一样,但是接口不同。Kernel提供了一组
  • 关于4.x内核的内核态socket编程问题(sock_create_kern) tags : linux socket linux内核态socket编程如何实现:(以tcp服务端举例) 1、sock_create_kern() 2、kernel_setsockopt()这一步为可去掉的,...
  • 内核态的socket编程

    千次阅读 2013-06-17 15:32:58
    记不清从哪个kernel版本开始,内核态就不能直接使用系统调用了。当然,socket的系统调用也不能用了。不过好在kernel提供了一组内核态的socket API。在net/socket.c文件中,可以看到这么几个导出符号: EXPORT_...
  • 一、背景--线程状态切换的代价 ...用户态切换至内核态需要传递给许多变量、参数给内核,内核也需要保护好用户态在切换时的一些寄存器值、变量等,以便内核态调用结束后切换回用户态继续工作。 synch...
  • 1、用户态和内核态的区别? 明白这两个概念之前,我们得知道用户空间和内核空间。 用户空间:指的就是用户可以操作和访问的空间,这个空间通常存放我们用户自己写的数据等。 内核空间:是系统内核来操作的一块...
  • 1. 简介 前篇博文(linux内核编程一:模块的装载和卸载)中我们...Linux本身提供丰富的系统调用(如ioctl、open)来实现用户态与内核态交互,此文基于getsockopt系统调用,介绍一种简单的用户态与内核态通信方法:增加
  • 用户态与内核态

    2020-11-25 16:54:39
    参考: 内核态(内核空间)和用户态(用户空间)的区别和联系 这个系列讲的也挺好的: Windows核心编程入门:7 用户态到内核态的穿越
  • 内核态编程指南 https://blog.csdn.net/yeshennet/article/details/82315604 内核态程序开发 内核态开发和用户态开发有很多相似之处,也有些不同之处。 相同之处 都要进行设计、开发、调试和优化的过程。 业务的开发...
  • 从图上我们可以看出来通过系统调用将Linux整个体系分为用户态和内核态(或者说内核空间和用户空间)。 系统调用 为了使应用程序访问到内核管理的资源例如CPU,内存,I/O。内核必须提供一组通用的访问接口,这些接口...
  • 与用户态同步相比,内核态同步耗时要多(用户态内核态切换),但内核同步能够跨进程同步,并使用灵活,以及配套的安全机制。 触发未触发状态 对于内核对象来说,均有触发及未触发状态,其状态转换规则因不同内核对象...
  • linux用户态和内核态

    千次阅读 2020-10-24 10:43:52
    内核态和用户态 对于linux中的内核态和用户态之间的关联,我觉得下面的图片很形象 该图片来源于:https://www.cnblogs.com/bakari/p/5520860.html 如上图所示,从宏观上来看,Linux操作系统的体系架构分为用户态和...
  • 用户态、内核态的理解 起因:“为了防止用户程序破坏操作系统或直接操作硬件,必须严格区分操作系统代码和用户代码。为此,许多处理机在处理机状态字(PSW)中增加了一个执行方式位,区分两种操作方式:用户态,内核...
  • 用户态和内核态切换

    千次阅读 2020-12-22 21:30:27
    从用户态到内核态切换可以通过三种方式,或者说会导致从用户态切换到内核态的操作: 系统调用,这个上面已经讲解过了,在我公众号之前的文章也有讲解过。其实系统调用本身就是中断,但是软件中断,跟硬中断不同。...
  • 用户态 内核态

    2015-08-22 12:07:12
    参考内核态代码不受限制,自由访问任何有效地址,进行直接端口访问 对应ring0 留给操作系统代码,设备驱动程序代码使用的用户态受处理器诸多检查,只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的...
  • 内核态基本套接字编程

    千次阅读 2013-08-04 20:42:00
    /*内核态套接字编程这一步很重要,在服务端是要建立客户端的socket结构*/ rc = sock_create_lite(PF_PACKET, sock->type, IPPROTO_TCP, &newsock); if (rc) { printk("Can't allocate socket\n"); return rc; ...
  • 本文基于ubuntu系统,linux内核3.0.0。 1.hello.c ... printk("The process is %s pid is %d\n", current->comm, ...由此说明:用户通过系统调用进入内核态;仍然保留对该进程在用户态时资源的使用。
  • 用户态和内核态之间的切换 切换方式 从用户态到内核态切换可以通过三种方式,或者说会导致从用户态切换到内核态的操作: 系统调用,这个上面已经讲解过了,在我公众号之前的文章也有讲解过。其实系统调用本身就是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 46,089
精华内容 18,435
关键字:

内核态编程