_____ From: Alexej Sokolov [mailto:bsd.qu...@googlemail.com] To: Gerry Weaver [mailto:ger...@compvia.com] Cc: freebsd-hackers@freebsd.org Sent: Thu, 15 Jan 2009 12:31:00 -0600 Subject: Re: How to access kernel memory from user space
2008/12/23 Gerry Weaver <ger...@compvia.com> Hello All, I am working on a driver that collects various network statistics via pfil. I have a simple array of structures that I use to store the statistics. I also have a user space process that needs to collect these statistics every second or so. A copy operation from kernel to user space would be too expensive. Is there a mechanism that would allow me to gain direct access to my kernel array from user space? The user process would only need read access. It seems like maybe this could be done with mmap, but since this is not a character driver, there is no device file etc.. I'm a newbie, so I apologize if this is something that should be obvious. Thanks in advance, Gerry _______________________________________________ freebsd-hackers@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-hackers To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org" Hi, some times ago I solve this task. That's my solution in a system call (whithout cdev). Thanx in advance for founded mistakes and possible bugs (-: #include <sys/param.h> #include <sys/proc.h> #include <sys/conf.h> #include <sys/module.h> #include <sys/sysent.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/sysproto.h> #include <sys/resourcevar.h> #include <vm/vm.h> #include <vm/pmap.h> #include <vm/vm_map.h> #include <vm/vm_param.h> #include <vm/vm_kern.h> #include <vm/vm_object.h> /* Arguments for syscall */ struct args { /* Pointer to allocated Buffer */ unsigned int *p; }; /* String to be located in maped buffer */ const char *str = "BSD IS SEXY"; /* Syscall func */ static int syscf(struct thread *td, void *sa) { int error; struct args *uap; vm_offset_t addr; /* Kernel space address */ vm_offset_t user_addr; /* User space address */ struct proc *procp = (struct proc *)td->td_proc; struct vmspace *vms = procp->p_vmspace; uap = (struct args *)sa; PROC_LOCK(procp); user_addr = round_page((vm_offset_t)vms->vm_daddr + lim_max(procp, RLIMIT_DATA)); PROC_UNLOCK(procp); MALLOC(addr, vm_offset_t, PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO); vm_map_entry_t myentry; vm_object_t myobject; vm_pindex_t mypindex; vm_prot_t myprot; boolean_t mywired; vm_ooffset_t objoffset; vm_map_lookup(&kmem_map, addr, VM_PROT_ALL, &myentry, &myobject, &mypindex, &myprot, &mywired); /* OUT */ vm_map_lookup_done(kmem_map, myentry); printf("---> Syscall: hint for allocating space = 0x%X\n", addr); if (myobject == kmem_object){ printf("---> Syscall: Yes, it is kmem_obj! \n"); } /* Offset in vm_object */ objoffset = addr - myentry->start + myentry->offset; printf("------> Syscall: Object offset = 0x%X \n", (unsigned int)objoffset); /* * Try to map kernel buffer to user space */ vm_object_reference(myobject); /* NEEDED Increment vm_obj references */ error = vm_map_find(&vms->vm_map, myobject, objoffset, (vm_offset_t *)&user_addr, PAGE_SIZE, TRUE, VM_PROT_RW, VM_PROT_RW, MAP_ENTRY_NOFAULT); if (error == KERN_SUCCESS) { /* copy string using kernel address */ size_t len; copystr(str, (void *)addr, 12, &len); /* * Tell to user process it's user space address */ *uap->p = user_addr; /* * Try to read the string using user space address */ printf("String: %s\n", (char *)*uap->p); printf("---> Syscall: user_addr for allocating space = 0x%X\n", user_addr); } return (0); } /* Sysent entity for syscall */ static struct sysent sc_sysent = { 1, /* Number of arguments */ syscf /* Syscall function */ }; /* Offset in sysent[] */ static int offset = NO_SYSCALL; /* Loader */ static int load (struct module *m, int cmd, void *something) { int error = 0; switch(cmd){ case MOD_LOAD: printf("Module with sysc loaded. Offset = %d \n", offset); break; case MOD_UNLOAD: printf("Module with sysc unloaded. Offset = %d \n", offset); break; default: error = EOPNOTSUPP; break; } return (error); } /* Syscall macro*/ SYSCALL_MODULE(fiveg_sysc, &offset, &sc_sysent, load, NULL); If needed, I can post user space program. Hi, This looks like a very nice solution. I would like to see the user space code very much. I really appreciate your help! Thanks Again, Gerry _______________________________________________ freebsd-hackers@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-hackers To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"