在操作系统中, 用户层(User Space)和 内核层(Kernel Space)是两个独立的地址空间,直接访问彼此的内存是不安全的。因此,数据传递需要通过特定的机制实现,确保安全性和隔离性。以下是数据传递的原理和Demo示例。
read()、
write()、
ioctl()等)请求内核服务。stdin、
stdout、套接字等)管理I/O资源。read()/
write()读写文件描述符,内核负责数据拷贝。ioctl() 和设备驱动ioctl()向设备驱动发送命令,传递自定义数据结构。copy_to_user() /
copy_from_user()read()/
write())c1#include <stdio.h>2#include <unistd.h>3#include <string.h>45int main() {6 char buf[256];7 const char *msg = "Hello from User Space!\n";89 // 写入数据到标准输出(内核通过write系统调用处理)10 write(STDOUT_FILENO, msg, strlen(msg));1112 // 从标准输入读取数据(内核通过read系统调用处理)13 ssize_t n = read(STDIN_FILENO, buf, sizeof(buf) - 1);14 if (n > 0) {15 buf[n] = '\0';16 printf("User received: %s", buf);17 }18 return 0;19}
write(STDOUT_FILENO, ...)时,内核的
write系统调用实现会:
copy_from_user())。/dev/tty)。ioctl()传递自定义数据c1#include <linux/module.h>2#include <linux/fs.h>3#include <linux/uaccess.h> // copy_to_user, copy_from_user45#define DEVICE_NAME "mydev"6#define IOCTL_MAGIC 'k'7#define IOCTL_SET_MSG _IOW(IOCTL_MAGIC, 1, char *)89static char kernel_buf[256];1011static long mydev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {12 switch (cmd) {13 case IOCTL_SET_MSG:14 if (copy_from_user(kernel_buf, (char *)arg, 256))15 return -EFAULT;16 printk(KERN_INFO "Kernel received: %s\n", kernel_buf);17 break;18 default:19 return -EINVAL;20 }21 return 0;22}2324static struct file_operations fops = {25 .owner = THIS_MODULE,26 .unlocked_ioctl = mydev_ioctl,27};2829static int __init mydev_init(void) {30 printk(KERN_INFO "Device loaded\n");31 return register_chrdev(0, DEVICE_NAME, &fops);32}3334static void __exit mydev_exit(void) {35 unregister_chrdev(0, DEVICE_NAME);36 printk(KERN_INFO "Device unloaded\n");37}3839module_init(mydev_init);40module_exit(mydev_exit);41MODULE_LICENSE("GPL");
c1#include <stdio.h>2#include <fcntl.h>3#include <unistd.h>4#include <sys/ioctl.h>56#define DEVICE_PATH "/dev/mydev"7#define IOCTL_SET_MSG _IOW('k', 1, char *)89int main() {10 int fd = open(DEVICE_PATH, O_RDWR);11 if (fd < 0) {12 perror("Failed to open device");13 return 1;14 }1516 char user_buf[] = "Hello from User Space via ioctl!";17 ioctl(fd, IOCTL_SET_MSG, user_buf); // 数据通过copy_from_user传递到内核1819 close(fd);20 return 0;21}
c1#include <linux/module.h>2#include <linux/mm.h>3#include <linux/highmem.h>45static char *shared_mem;67static int __init shared_mem_init(void) {8 shared_mem = (char *)__get_free_page(GFP_KERNEL);9 if (!shared_mem) {10 printk(KERN_ERR "Failed to allocate memory\n");11 return -ENOMEM;12 }13 strcpy(shared_mem, "Hello from Kernel!");14 <"xawrsd.com"> <"msans.com.cn"> <"xeixei.com"> printk(KERN_INFO "Shared memory address: %p\n", shared_mem);15 return 0;16}1718static void __exit shared_mem_exit(void) {19 free_page((unsigned long)shared_mem);20 printk(KERN_INFO "Shared memory freed\n");21}2223module_init(shared_mem_init);24module_exit(shared_mem_exit);25MODULE_LICENSE("GPL");
c1#include <stdio.h>2#include <sys/mman.h>3#include <fcntl.h>4#include <unistd.h>56#define SHM_SIZE 409678int main() {9 int fd = open("/dev/mem", O_RDWR | O_SYNC);10 if (fd < 0) {11 perror("Failed to open /dev/mem");12 return 1;13 }1415 // 假设已知内核共享内存的物理地址(实际需通过设备文件传递)16 void *addr = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xPHYSICAL_ADDR);17 if (addr == MAP_FAILED) {18 perror("mmap failed");19 close(fd);20 return 1;21 }2223 printf("User received: %s\n", (char *)addr);24 <"njkernel.com"> <"weichengpiping.com"> <"cjw-online.com"> munmap(addr, SHM_SIZE);25 close(fd);26 return 0;27}
注意:实际共享内存需通过设备文件或
/proc接口传递物理地址,直接访问/dev/mem需要root权限且不安全。
安全性:内核必须验证用户空间指针(
copy_from_user()/
copy_to_user())。
<"addvv.com"> <"hc-electronics.com"> <"xiamusic.com">
read()/
write())。ioctl()。通过合理选择机制,可以安全高效地实现用户层与内核层的数据交互。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/19545/viewspace-3099845/ ,如需转载,请注明出处,否则将追究法律责任。