Linux内核态与用户态进程通信方法-用户上下文
来源:互联网 发布:kafka java heap space 编辑:程序博客网 时间:2024/05/14 17:12
运行在用户上下文环境中的代码是可以阻塞的,这样,便可以使用消息队列和 UNIX 域套接字来实现内核态与用户态的通信。但这些方法的数据传输效率较低,Linux 内核提供 copy_from_user()/copy_to_user() 函数来实现内核态与用户态数据的拷贝,但这两个函数会引发阻塞,所以不能用在硬、软中断中。一般将这两个特殊拷贝函数用在类似于系统调用一类的函数中,此类函数在使用中往往"穿梭"于内核态与用户态。此类方法的工作原理路如图【1】。
其中相关的系统调用是需要用户自行编写并载入内核。
内核模块注册了一组设置套接字选项的函数使得用户空间进程可以调用此组函数对内核态数据进行读写。源码包含三个文件,imp1.h 是通用头文件,定义了用户态和内核态都要用到的宏。imp1_k.c 是内核模块的源代码。imp1_u.c 是用户态进程的源代码。整个示例演示了由一个用户态进程向用户上下文环境发送一个字符串,内容为"a message from userspace\n"。然后再由用户上下文环境向用户态进程发送一个字符串,内容为"a message from kernel\n"。
1 内核代码:
/*imp1_k.c*/ 2 #ifndef __KERNEL__ 3 #define __KERNEL__ 4 #endif 5 6 #ifndef MODULE 7 #define MODULE 8 #endif 9 10 #include <linux/module.h> 11 #include <linux/kernel.h> 12 #include <linux/types.h> 13 #include <linux/string.h> 14 #include <linux/netfilter_ipv4.h> 15 #include <linux/init.h> 16 #include <asm/uaccess.h> 17 #include "imp1.h" 18 19 #define KMSG "a message from kernel\n" 20 #define KMSG_LEN sizeof("a message from kernel\n") 21 MODULE_LICENSE("Dual BSD/GPL"); 22 static int data_to_kernel(struct sock *sk, int cmd, void *user, 23 unsigned int len) 24 { 25 switch(cmd) 26 { 27 case IMP1_SET: 28 { 29 char umsg[64]; 30 memset(umsg, 0, sizeof(char)*64); 31 copy_from_user(umsg, user, sizeof(char)*64); 32 printk("umsg: %s", umsg); 33 } 34 break; 35 } 36 return 0; 37 } 38 39 static int data_from_kernel(struct sock *sk, int cmd, void *user, int *len) 40 { 41 switch(cmd) 42 { 43 case IMP1_GET: 44 { 45 copy_to_user(user, KMSG, KMSG_LEN); 46 } 47 break; 48 } 49 return 0; 50 } 51 52 static struct nf_sockopt_ops imp1_sockops = 53 { 54 .pf = PF_INET, 55 .set_optmin = IMP1_SET, 56 .set_optmax = IMP1_MAX, 57 .set = data_to_kernel, 58 .get_optmin = IMP1_GET, 59 .get_optmax = IMP1_MAX, 60 .get = data_from_kernel, 61 }; 62 63 static int __init init(void) 64 { 65 return nf_register_sockopt(&imp1_sockops); 66 } 67 68 static void __exit fini(void) 69 { 70 nf_unregister_sockopt(&imp1_sockops); 71 } 72 73 module_init(init); 74 module_exit(fini); 75
二 应用层代码:
/*imp1_u.c*/ 2 #include <unistd.h> 3 #include <stdio.h> 4 #include <sys/socket.h> 5 #include <linux/in.h> 6 #include "imp1.h" 7 8 #define UMSG "a message from userspace\n" 9 #define UMSG_LEN sizeof("a message from userspace\n") 10 11 char kmsg[64]; 12 13 int main(void) 14 { 15 int sockfd; 16 int len; 17 18 sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); 19 if(sockfd < 0) 20 { 21 printf("can not create a socket\n"); 22 return -1; 23 } 24 25 /*call function data_to_kernel()*/ 26 setsockopt(sockfd, IPPROTO_IP, IMP1_SET, UMSG, UMSG_LEN); 27 28 len = sizeof(char)*64; 29 30 /*call function data_from_kernel()*/ 31 getsockopt(sockfd, IPPROTO_IP, IMP1_GET, kmsg, &len); 32 printf("kmsg: %s", kmsg); 33 34 close(sockfd); 35 return 0; 36 }
三头文件:
1 /*imp1.h*/ 2 #ifndef __IMP1_H__ 3 #define __IMP1_H__ 4 5 #define IMP1_OPS_BASIC 128 6 #define IMP1_SET IMP1_OPS_BASIC 7 #define IMP1_GET IMP1_OPS_BASIC 8 #define IMP1_MAX IMP1_OPS_BASIC+1 9 10 #endif~
四 编译后运行结果:
内核打印:[541380.295993] umsg: a message from userspace
[541390.819256] umsg: a message from userspace
[541392.515414] umsg: a message from userspace
[541393.374753] umsg: a message from userspace
[541393.967123] umsg: a message from userspace
应用程序打印:
/imp1$ sudo ./imp1_u
kmsg: a message from kernel
- Linux内核态与用户态进程通信方法-用户上下文
- linux 用户态和内核态以及进程上下文、中断上下文 内核空间用户空间理解
- Linux内核态与用户态通信的常用方法
- Linux内核态与用户态通信的常用方法
- Linux内核态与用户态通信的常用方法
- Linux内核态与用户态通信的常用方法
- linux 内核进程与用户进程的通信 方法一 使用sockopt与内核交换数据
- linux 内核进程与用户进程的通信 方法一 使用sockopt与内核交换数据
- linux 内核进程与用户进程的通信 方法一 使用sockopt与内核交换数据
- 内核空间和用户空间,内核态和用户态,进程上下文和中断上下文
- 用户空间与内核空间,进程上下文与中断上下文
- 用户空间与内核空间,进程上下文与中断上下文
- Linux用户空间与内核空间,进程上下文与中断上下文
- 用户空间和内核空间、进程上下文与中断上下文
- Linux内核中进程上下文、中断上下文、原子上下文、用户上下文的理解
- linux用户态与内核态通信netlink
- linux内核态与用户态通信方式
- linux用户态和内核态通信
- db_load命令用法
- asm1
- c#验证码问题
- s19文件格式详解
- 一道小巧的编程难题(高手进,请教思路)
- Linux内核态与用户态进程通信方法-用户上下文
- 最全的解决方案,安卓手机gps定位慢怎么办?轻松几步搞定
- Spring的注入方式
- NYOJ 40 公约数和公倍数
- 安卓开发环境搭建软件下载
- VECTOR的常用操作(更新)
- 搭讪技巧,希望所有单身的程序员兄弟都有女朋友哦!!
- ubuntu 系统 安装qq
- Java学习之路:不走弯路,就是捷径