The way Linux kernel and user space communicate (i)-proc files and mmap shared memory __linux

Source: Internet
Author: User
Tags sprintf

Dynamically passes the physical address and size of the kernel space to user space. This article also demonstrates two common methods that can be used for communication between kernel space and user space: Proc file system and Mmap shared memory.
The entire kernel module, when the module inserts, establishes the proc file, allocates the memory. When the module is unloaded, the content written by the user space is printed.
Here is the code for the kernel module and the test code for user space.

/*this program are used to allocate memory in kernel
and pass the physical address to userspace through proc file.*/

#include <linux/version.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/mm.h>

#define PROC_MEMSHARE_DIR "Memshare"
#define PROC_MEMSHARE_PHYADDR "Phymem_addr"
#define PROC_MEMSHARE_SIZE "Phymem_size"

/*alloc one page. 4096 bytes*/
#define Page_order 0
/*this value can get from page_order*/
#define PAGES_NUMBER 1

struct Proc_dir_entry *proc_memshare_dir;
unsigned long kernel_memaddr = 0;
unsigned long kernel_memsize= 0;

static int proc_read_phymem_addr (char *page, Char **start, off_t off, int count)
{
return sprintf (page, "%08lx/n", __pa (KERNEL_MEMADDR));
}
static int proc_read_phymem_size (char *page, Char **start, off_t off, int count)
{
return sprintf (page, "%lu/n", kernel_memsize);
}

static int __init init (void)
{
/*build proc dir "Memshare" and two proc files:phymem_addr, phymem_size in the dir*/
Proc_memshare_dir = Proc_mkdir (Proc_memshare_dir, NULL);
Create_proc_info_entry (proc_memshare_phyaddr, 0, Proc_memshare_dir, proc_read_phymem_addr);
Create_proc_info_entry (proc_memshare_size, 0, Proc_memshare_dir, proc_read_phymem_size);

/*alloc One page*/
Kernel_memaddr =__get_free_pages (Gfp_kernel, Page_order);
if (!KERNEL_MEMADDR)
{
PRINTK ("Allocate memory failure!/n");
}
Else
{
Setpagereserved (Virt_to_page (KERNEL_MEMADDR));

In the kernel after the application to the page, to call the setpagereserved, the equivalent of telling the system, this page I already accounted for. You should do this for every page you apply to.

Kernel_memsize = Pages_number * page_size;
PRINTK ("Allocate memory success!.") The PHY mem addr=%08lx, size=%lu/n ", __pa (KERNEL_MEMADDR), kernel_memsize);
}
return 0;
}

static void __exit fini (void)
{
PRINTK ("The content written by user is:%s/n", (unsigned char *) kernel_memaddr);
Clearpagereserved (Virt_to_page (KERNEL_MEMADDR));
Free_pages (KERNEL_MEMADDR, Page_order);
Remove_proc_entry (PROC_MEMSHARE_PHYADDR, Proc_memshare_dir);
Remove_proc_entry (Proc_memshare_size, Proc_memshare_dir);
Remove_proc_entry (Proc_memshare_dir, NULL);

Return
}
Module_init (init);
Module_exit (fini);
Module_license ("GPL");
Module_author ("Godbach ([Email]nylzhaowei@163.com[/email])");
Module_description ("Kernel memory Share module.");


Test code for User space:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>

int main (int argc, char* argv[])
{
if (argc!= 2)
{
printf ("Usage:%s string/n", argv[0]);
return 0;
}

unsigned long phymem_addr, phymem_size;
Char *map_addr;
Char s[256];
int FD;

/*get the physical address of allocated memory in kernel*/
FD = open ("/proc/memshare/phymem_addr", o_rdonly);
if (FD < 0)
{
printf ("Cannot open file/proc/memshare/phymem_addr/n");
return 0;
}
Read (fd, S, sizeof (s));
SSCANF (S, "%LX", &phymem_addr);
Close (FD);

/*get the size of allocated memory in kernel*/
FD = open ("/proc/memshare/phymem_size", o_rdonly);
if (FD < 0)
{
printf ("Cannot open file/proc/memshare/phymem_size/n");
return 0;
}
Read (fd, S, sizeof (s));
SSCANF (S, "%lu", &phymem_size);
Close (FD);

printf ("Phymem_addr=%lx, phymem_size=%lu/n", phymem_addr, phymem_size);
/*memory map*/
int map_fd = open ("/dev/mem", O_RDWR);
if (MAP_FD < 0)
{
printf ("Cannot open file/dev/mem/n");
return 0;
}

map_addr = mmap (0, Phymem_size, prot_read| Prot_write, map_shared, MAP_FD, phymem_addr);
strcpy (MAP_ADDR, argv[1]);
Munmap (MAP_ADDR, phymem_size);
Close (MAP_FD);
return 0;

}

The kernel of the test is 2.6.25. The following are the results of the execution.

debian:/home/km/memshare# Insmod Memshare_kernel.ko
debian:/home/km/memshare#./memshare_user ' hello,world! '
phymem_addr=e64e000, phymem_size=4096
debian:/home/km/memshare# cat/proc/memshare/phymem_addr
0e64e000
debian:/home/km/memshare# cat/proc/memshare/phymem_size
4096
debian:/home/km/memshare# Rmmod Memshare_kernel
debian:/home/km/memshare# tail/var/log/messages
Sep 18:14:24 Debian kernel: [50527.567931] Allocate memory success!. The PHY mem addr=0e64e000, size=4096
Sep 18:15:31 Debian kernel: [50592.570986] The content written by user is:hello,world!

In this way, you want to apply for 4M of memory,

static int __init init (void)
{
char * PADDR;
int order = 0;
int offset = 0;
int tmp = 0;

/*build proc dir "Memshare" and two proc files:phymem_addr, phymem_size in the dir*/
Proc_memshare_dir = Proc_mkdir (Proc_memshare_dir, NULL);
Create_proc_info_entry (proc_memshare_phyaddr, 0, Proc_memshare_dir, proc_read_phymem_addr);
Create_proc_info_entry (proc_memshare_size, 0, Proc_memshare_dir, proc_read_phymem_size);

/*alloc One page*/
Kernel_memaddr =__get_free_pages (Gfp_kernel, Page_order);
[Color=royalblue] order = Get_order (4000000);
Kernel_memaddr =__get_free_pages (Gfp_kernel, order);
[/color]
if (!KERNEL_MEMADDR)
{
PRINTK ("Allocate memory failure!/n");
}
Else
{
Setpagereserved (Virt_to_page (KERNEL_MEMADDR));

Kernel_memsize = Pages_number * page_size;
[Color=royalblue] kernel_memsize = ((4000000-1) >> page_shift) * page_size; [/color]
[Color= #4169e1] [/color]
[Color=black] ... [/color]
[Color=black]} [/color]
[Color=black] [/color]
[Color=black] [/color]
I write the data to the first page (4k range) in the kernel, which can be read in the user state, but if you write the data to another page in the future, the user state will not be able to attend it.
This is also true for user state writes.

needs to be performed on each 4k page: setpagereserved (Virt_to_page (KERNEL_MEMADDR));

In the kernel after the application to the page, to call the setpagereserved, the equivalent of telling the system, this page I already accounted for. You should do this for every page you apply to.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.