修改目录结构...
@@ -0,0 +1,22 @@
|
||||
ROOT=$(shell pwd)
|
||||
|
||||
DIRS=param process memory
|
||||
|
||||
|
||||
|
||||
all:
|
||||
for i in $(DIRS); do \
|
||||
(cd $$i && echo "making $$i" && $(MAKE) ) || exit 1; \
|
||||
done
|
||||
|
||||
clean:
|
||||
for i in $(DIRS); do \
|
||||
(cd $$i && echo "cleaning $$i" && $(MAKE) clean) || exit 1; \
|
||||
done
|
||||
|
||||
install :
|
||||
# for i in $(DIRS); do \
|
||||
# (cd $$i && echo "install $$i" && $(MAKE) install) || exit 1; \
|
||||
# done
|
||||
cp $(INJECTOR)/memInjector $(BIN)/memInjector
|
||||
cp $(ENGINE)/memoryEngine.ko $(BIN)/memoryEngine.ko
|
||||
@@ -0,0 +1 @@
|
||||
https://android.googlesource.com/kernel/common/+/bcmdhd-3.10/samples/hidraw/hid-example.c
|
||||
@@ -0,0 +1 @@
|
||||
cmd_/home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/kfifo/test.ko := ld -r -m elf_x86_64 -T ./scripts/module-common.lds --build-id -o /home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/kfifo/test.ko /home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/kfifo/test.o /home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/kfifo/test.mod.o
|
||||
@@ -0,0 +1,2 @@
|
||||
/home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/kfifo/test.ko
|
||||
/home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/kfifo/test.o
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
obj-m := test.o
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
PWD := $(shell pwd)
|
||||
|
||||
all:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kfifo.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("zl");
|
||||
MODULE_VERSION("V1.0");
|
||||
MODULE_DESCRIPTION("kfifo test");
|
||||
|
||||
struct KfifoNode
|
||||
{
|
||||
unsigned int num;
|
||||
char *string;
|
||||
};
|
||||
|
||||
char *array[] =
|
||||
{
|
||||
"abcdefg",
|
||||
"gfedcba",
|
||||
"aaaaa",
|
||||
"bbbb",
|
||||
"ccc",
|
||||
"dd",
|
||||
"e",
|
||||
"12345",
|
||||
"1234",
|
||||
"123",
|
||||
"12",
|
||||
"1",
|
||||
"1111",
|
||||
};
|
||||
|
||||
#define TAB_SIZE(array) (sizeof(array)/sizeof(array[0]))
|
||||
|
||||
static struct __kfifo *pkfifoSpace = NULL;
|
||||
static spinlock_t fifoLock;
|
||||
|
||||
static void kfifo_check(char* str, int line, struct kfifo* pkfifo)
|
||||
{
|
||||
if(pkfifo != NULL)
|
||||
{
|
||||
printk("[%s-%d]: pkfifo->size = %d\t pkfifo->in = %d\t pkfifo->out = %d\t \n",
|
||||
str, line, kfifo_size(pkfifo), pkfifo->in, pkfifo->out);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init mykfifo_init(void)
|
||||
{
|
||||
int i;
|
||||
struct KfifoNode *pstNode;
|
||||
|
||||
pkfifoSpace = kfifo_alloc((sizeof(struct KfifoNode) << 4), GFP_KERNEL, &fifoLock);
|
||||
if (pkfifoSpace == NULL)
|
||||
{
|
||||
printk("kfifo_alloc failed !\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
spin_lock_init(&fifoLock); //Initial fifo spinlock
|
||||
pstNode = kzalloc(sizeof(struct KfifoNode), GFP_KERNEL);
|
||||
|
||||
/****************************************************************/
|
||||
printk("*****************************************************\n");
|
||||
kfifo_check((char *)__func__, __LINE__, pkfifoSpace);
|
||||
for(i = 0; i < TAB_SIZE(array); i++)
|
||||
{
|
||||
pstNode->num = i;
|
||||
pstNode->string = (char *)array[i];
|
||||
kfifo_put(pkfifoSpace, (unsigned char *)pstNode, sizeof(struct KfifoNode)); //将数据写入缓冲区
|
||||
kfifo_check((char *)__func__, __LINE__, pkfifoSpace);
|
||||
printk("[%s-%d]:Num is: %d, Message is: %s\n", __func__, __LINE__, pstNode->num, pstNode->string);
|
||||
}
|
||||
/***************************************************************/
|
||||
|
||||
printk("-----------------------------------------------------\n");
|
||||
if(!kfifo_len(pkfifoSpace))
|
||||
{
|
||||
printk("[%s-%d]: kfifo_len return 0, test failed !!! \n", __func__, __LINE__);
|
||||
kfifo_reset(pkfifoSpace);
|
||||
kfifo_free(pkfifoSpace);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < TAB_SIZE(array); i++)
|
||||
{
|
||||
kfifo_get(pkfifoSpace, (unsigned char *)pstNode, sizeof(struct KfifoNode));
|
||||
kfifo_check((char *)__func__, __LINE__, pkfifoSpace);
|
||||
printk("[%s-%d]: Num is: %d, fifoMessage is: %s\n", __func__, __LINE__, pstNode->num, pstNode->string);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
printk("-----------------------------------------------------\n");
|
||||
kfifo_check((char *)__func__, __LINE__, pkfifoSpace);
|
||||
|
||||
kfree(pstNode);
|
||||
kfifo_reset(pkfifoSpace);
|
||||
kfifo_free(pkfifoSpace);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void __exit mykfifo_exit(void)
|
||||
{
|
||||
printk("exit !\n");
|
||||
}
|
||||
|
||||
module_init(mykfifo_init);
|
||||
module_exit(mykfifo_exit);
|
||||
@@ -0,0 +1,41 @@
|
||||
/*************************************************************************
|
||||
> File Name: 1.c
|
||||
> Author: gatieme
|
||||
> Created Time: Thu 07 Apr 2016 02:44:43 PM CST
|
||||
************************************************************************/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
static int kfifo_init()
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int val;
|
||||
ret = 1;
|
||||
/* */
|
||||
for(i = 0; i < 32; i++)
|
||||
{
|
||||
kfifo_in(fifo, &i, sizeof(i));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void kfifo_exit( )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
module_init(list_kfifo_init);
|
||||
module_exit(list_kfifo_exit);
|
||||
|
||||
MODULE_AUTHOR("gatieme");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
kernel//home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/kfifo/test.ko
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Sample fifo dma implementation
|
||||
*
|
||||
* Copyright (C) 2010 Stefani Seibold <stefani@seibold.net>
|
||||
*
|
||||
* Released under the GPL version 2 only.
|
||||
*
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kfifo.h>
|
||||
/*
|
||||
* This module shows how to handle fifo dma operations.
|
||||
*/
|
||||
/* fifo size in elements (bytes) */
|
||||
#define FIFO_SIZE 32
|
||||
static struct kfifo fifo;
|
||||
static int __init example_init(void)
|
||||
{
|
||||
int i;
|
||||
unsigned int ret;
|
||||
unsigned int nents;
|
||||
struct scatterlist sg[10];
|
||||
printk(KERN_INFO "DMA fifo test start\n");
|
||||
if (kfifo_alloc(&fifo, FIFO_SIZE, GFP_KERNEL)) {
|
||||
printk(KERN_WARNING "error kfifo_alloc\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
printk(KERN_INFO "queue size: %u\n", kfifo_size(&fifo));
|
||||
kfifo_in(&fifo, "test", 4);
|
||||
for (i = 0; i != 9; i++)
|
||||
kfifo_put(&fifo, &i);
|
||||
/* kick away first byte */
|
||||
kfifo_skip(&fifo);
|
||||
printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo));
|
||||
/*
|
||||
* Configure the kfifo buffer to receive data from DMA input.
|
||||
*
|
||||
* .--------------------------------------.
|
||||
* | 0 | 1 | 2 | ... | 12 | 13 | ... | 31 |
|
||||
* |---|------------------|---------------|
|
||||
* \_/ \________________/ \_____________/
|
||||
* \ \ \
|
||||
* \ \_allocated data \
|
||||
* \_*free space* \_*free space*
|
||||
*
|
||||
* We need two different SG entries: one for the free space area at the
|
||||
* end of the kfifo buffer (19 bytes) and another for the first free
|
||||
* byte at the beginning, after the kfifo_skip().
|
||||
*/
|
||||
sg_init_table(sg, ARRAY_SIZE(sg));
|
||||
nents = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE);
|
||||
printk(KERN_INFO "DMA sgl entries: %d\n", nents);
|
||||
if (!nents) {
|
||||
/* fifo is full and no sgl was created */
|
||||
printk(KERN_WARNING "error kfifo_dma_in_prepare\n");
|
||||
return -EIO;
|
||||
}
|
||||
/* receive data */
|
||||
printk(KERN_INFO "scatterlist for receive:\n");
|
||||
for (i = 0; i < nents; i++) {
|
||||
printk(KERN_INFO
|
||||
"sg[%d] -> "
|
||||
"page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n",
|
||||
i, sg[i].page_link, sg[i].offset, sg[i].length);
|
||||
if (sg_is_last(&sg[i]))
|
||||
break;
|
||||
}
|
||||
/* put here your code to setup and exectute the dma operation */
|
||||
/* ... */
|
||||
/* example: zero bytes received */
|
||||
ret = 0;
|
||||
/* finish the dma operation and update the received data */
|
||||
kfifo_dma_in_finish(&fifo, ret);
|
||||
/* Prepare to transmit data, example: 8 bytes */
|
||||
nents = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8);
|
||||
printk(KERN_INFO "DMA sgl entries: %d\n", nents);
|
||||
if (!nents) {
|
||||
/* no data was available and no sgl was created */
|
||||
printk(KERN_WARNING "error kfifo_dma_out_prepare\n");
|
||||
return -EIO;
|
||||
}
|
||||
printk(KERN_INFO "scatterlist for transmit:\n");
|
||||
for (i = 0; i < nents; i++) {
|
||||
printk(KERN_INFO
|
||||
"sg[%d] -> "
|
||||
"page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n",
|
||||
i, sg[i].page_link, sg[i].offset, sg[i].length);
|
||||
if (sg_is_last(&sg[i]))
|
||||
break;
|
||||
}
|
||||
/* put here your code to setup and exectute the dma operation */
|
||||
/* ... */
|
||||
/* example: 5 bytes transmitted */
|
||||
ret = 5;
|
||||
/* finish the dma operation and update the transmitted data */
|
||||
kfifo_dma_out_finish(&fifo, ret);
|
||||
ret = kfifo_len(&fifo);
|
||||
printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo));
|
||||
if (ret != 7) {
|
||||
printk(KERN_WARNING "size mismatch: test failed");
|
||||
return -EIO;
|
||||
}
|
||||
printk(KERN_INFO "test passed\n");
|
||||
return 0;
|
||||
}
|
||||
static void __exit example_exit(void)
|
||||
{
|
||||
kfifo_free(&fifo);
|
||||
}
|
||||
|
||||
module_init(example_init);
|
||||
module_exit(example_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");
|
||||
@@ -0,0 +1,36 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/vermagic.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
MODULE_INFO(vermagic, VERMAGIC_STRING);
|
||||
|
||||
__visible struct module __this_module
|
||||
__attribute__((section(".gnu.linkonce.this_module"))) = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.init = init_module,
|
||||
#ifdef CONFIG_MODULE_UNLOAD
|
||||
.exit = cleanup_module,
|
||||
#endif
|
||||
.arch = MODULE_ARCH_INIT,
|
||||
};
|
||||
|
||||
static const struct modversion_info ____versions[]
|
||||
__used
|
||||
__attribute__((section("__versions"))) = {
|
||||
{ 0xa139692d, __VMLINUX_SYMBOL_STR(module_layout) },
|
||||
{ 0xdb760f52, __VMLINUX_SYMBOL_STR(__kfifo_free) },
|
||||
{ 0x274d08dc, __VMLINUX_SYMBOL_STR(__kfifo_dma_out_prepare) },
|
||||
{ 0x89afe34e, __VMLINUX_SYMBOL_STR(__kfifo_dma_in_prepare) },
|
||||
{ 0xc897c382, __VMLINUX_SYMBOL_STR(sg_init_table) },
|
||||
{ 0xf23fcb99, __VMLINUX_SYMBOL_STR(__kfifo_in) },
|
||||
{ 0x97868aef, __VMLINUX_SYMBOL_STR(__kfifo_alloc) },
|
||||
{ 0x27e1a049, __VMLINUX_SYMBOL_STR(printk) },
|
||||
};
|
||||
|
||||
static const char __module_depends[]
|
||||
__used
|
||||
__attribute__((section(".modinfo"))) =
|
||||
"depends=";
|
||||
|
||||
|
||||
MODULE_INFO(srcversion, "2EDF0BDCF3E6712FA08ADE3");
|
||||
@@ -0,0 +1,22 @@
|
||||
ROOT=../
|
||||
|
||||
DIRS=mem mmap v2p
|
||||
|
||||
|
||||
|
||||
all:
|
||||
for i in $(DIRS); do \
|
||||
(cd $$i && echo "making $$i" && $(MAKE) ) || exit 1; \
|
||||
done
|
||||
|
||||
clean:
|
||||
for i in $(DIRS); do \
|
||||
(cd $$i && echo "cleaning $$i" && $(MAKE) clean) || exit 1; \
|
||||
done
|
||||
|
||||
install :
|
||||
# for i in $(DIRS); do \
|
||||
# (cd $$i && echo "install $$i" && $(MAKE) install) || exit 1; \
|
||||
# done
|
||||
cp $(INJECTOR)/memInjector $(BIN)/memInjector
|
||||
cp $(ENGINE)/memoryEngine.ko $(BIN)/memoryEngine.ko
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
obj-m := mem_dev.o
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
PWD := $(shell pwd)
|
||||
|
||||
all:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*************************************************************************
|
||||
> File Name: process.c
|
||||
> Author: GatieMe
|
||||
> Mail: gatieme@163.com
|
||||
> Created Time: 2016年04月01日 星期五 21时09分29秒
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
|
||||
|
||||
//#define METHOD 2
|
||||
static unsigned int METHOD = 1;
|
||||
module_param(METHOD, uint,0400);
|
||||
|
||||
long readPhysicsAddress(unsigned long pa, int *pStatus);
|
||||
|
||||
long writePhysicsAddress(unsigned long pa, unsigned long data, int *pStatus);
|
||||
|
||||
|
||||
|
||||
static int mem_dev_init(void)
|
||||
{
|
||||
readPhysicsAddress(0x12345, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mem_dev_exit(void)
|
||||
{
|
||||
printk( KERN_ALERT "GOOD BYE!!\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** add by gatieme */
|
||||
/*
|
||||
*
|
||||
*/
|
||||
long readPhysicsAddress(unsigned long pa, int *pStatus)
|
||||
{
|
||||
long data = -1;
|
||||
data = *(long *)pa;
|
||||
printk(KERN_INFO "physics address : 0x%lx, data : 0x%lx", pa, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
long writePhysicsAddress(unsigned long pa, unsigned long data, int *pStatus)
|
||||
{
|
||||
long oldData = -1;
|
||||
|
||||
oldData = *(long *)pa;
|
||||
printk(KERN_INFO "physics address : 0x%lx, old data : 0x%lx", pa, *(long *)pa);
|
||||
|
||||
*(long *)pa = data;
|
||||
printk(KERN_INFO "physics address : 0x%lx, new data : 0x%lx", pa, *(long *)pa);
|
||||
|
||||
return oldData;
|
||||
}
|
||||
|
||||
module_init(mem_dev_init);
|
||||
module_exit(mem_dev_exit);
|
||||
|
||||
MODULE_AUTHOR("gatieme");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,58 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define DEVKMEM "/dev/kmem"
|
||||
|
||||
#define PAGE_SIZE 0x1000
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if(argc != 2)
|
||||
{
|
||||
printf("usage...");
|
||||
exit(-1);
|
||||
}
|
||||
int fd;
|
||||
char *mbase;
|
||||
char read_buf[10];
|
||||
unsigned int regAddr;
|
||||
unsigned int varAddr;
|
||||
|
||||
varAddr = strtoul(argv[1], 0, 16);
|
||||
|
||||
unsigned int ptr = varAddr & ~(PAGE_MASK);
|
||||
|
||||
fd = open(DEVKMEM, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
printf("%s %d", __func__, __LINE__);
|
||||
perror("open");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
mbase = (char *)mmap(0, PAGE_SIZE, PROT_READ, MAP_SHARED,fd, (varAddr & PAGE_MASK));
|
||||
if (mbase == MAP_FAILED)
|
||||
{
|
||||
printf("map failed %s\n",strerror(errno));
|
||||
}
|
||||
|
||||
printf("varAddr = 0x%X \n", varAddr);
|
||||
printf("mapbase = 0x%X \n", (unsigned int)mbase);
|
||||
printf("value = 0x%X \n",*(unsigned int*)(mbase+ptr));
|
||||
printf("char = %c%c%c%c \n",
|
||||
*(char *)(mbase+ptr), *(char *)(mbase+ptr+1),
|
||||
*(char *)(mbase+ptr+2), *(char *)(mbase+ptr+3));
|
||||
|
||||
close(fd);
|
||||
munmap(mbase,PAGE_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* devmem2.c: Simple program to read/write from/to any location in memory.
|
||||
*
|
||||
* Copyright (C) 2000, Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
|
||||
*
|
||||
*
|
||||
* This software has been developed for the LART computing board
|
||||
* (http://www.lart.tudelft.nl/). The development has been sponsored by
|
||||
* the Mobile MultiMedia Communications (http://www.mmc.tudelft.nl/)
|
||||
* and Ubiquitous Communications (http://www.ubicom.tudelft.nl/)
|
||||
* projects.
|
||||
*
|
||||
* The author can be reached at:
|
||||
*
|
||||
* Jan-Derk Bakker
|
||||
* Information and Communication Theory Group
|
||||
* Faculty of Information Technology and Systems
|
||||
* Delft University of Technology
|
||||
* P.O. Box 5031
|
||||
* 2600 GA Delft
|
||||
* The Netherlands
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <termios.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
|
||||
__LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)
|
||||
|
||||
#define MAP_SIZE 4096UL
|
||||
#define MAP_MASK (MAP_SIZE - 1)
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int fd;
|
||||
void *map_base, *virt_addr;
|
||||
unsigned long read_result, writeval;
|
||||
off_t target;
|
||||
int access_type = 'w';
|
||||
|
||||
if(argc < 2) {
|
||||
fprintf(stderr, "\nUsage:\t%s { address } [ type [ data ] ]\n"
|
||||
"\taddress : memory address to act upon\n"
|
||||
"\ttype : access operation type : [b]yte, [h]alfword, [w]ord\n"
|
||||
"\tdata : data to be written\n\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
target = strtoul(argv[1], 0, 0);
|
||||
|
||||
if(argc > 2)
|
||||
access_type = tolower(argv[2][0]);
|
||||
|
||||
|
||||
if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
|
||||
printf("/dev/mem opened.\n");
|
||||
fflush(stdout);
|
||||
|
||||
/* Map one page */
|
||||
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
|
||||
if(map_base == (void *) -1) FATAL;
|
||||
printf("Memory mapped at address %p.\n", map_base);
|
||||
fflush(stdout);
|
||||
|
||||
virt_addr = map_base + (target & MAP_MASK);
|
||||
switch(access_type) {
|
||||
case 'b':
|
||||
read_result = *((unsigned char *) virt_addr);
|
||||
break;
|
||||
case 'h':
|
||||
read_result = *((unsigned short *) virt_addr);
|
||||
break;
|
||||
case 'w':
|
||||
read_result = *((unsigned long *) virt_addr);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Illegal data type '%c'.\n", access_type);
|
||||
exit(2);
|
||||
}
|
||||
printf("Value at address 0x%X (%p): 0x%X\n", target, virt_addr, read_result);
|
||||
fflush(stdout);
|
||||
|
||||
if(argc > 3)
|
||||
{
|
||||
writeval = strtoul(argv[3], 0, 0);
|
||||
switch(access_type) {
|
||||
case 'b':
|
||||
*((unsigned char *) virt_addr) = writeval;
|
||||
read_result = *((unsigned char *) virt_addr);
|
||||
break;
|
||||
case 'h':
|
||||
*((unsigned short *) virt_addr) = writeval;
|
||||
read_result = *((unsigned short *) virt_addr);
|
||||
break;
|
||||
case 'w':
|
||||
*((unsigned long *) virt_addr) = writeval;
|
||||
read_result = *((unsigned long *) virt_addr);
|
||||
break;
|
||||
}
|
||||
printf("Written 0x%X; readback 0x%X\n", writeval, read_result);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
if(munmap(map_base, MAP_SIZE) == -1) FATAL;
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
|
||||
/*
|
||||
* getjiff.c
|
||||
*
|
||||
* this toolkit shows how to get jiffies value from user space:
|
||||
* 1. find jiffies's address from kernel image.
|
||||
* 2. access virtual address space to get jiffies value.
|
||||
* 3. access physical address sapce to get jiffies value.
|
||||
*
|
||||
* demostrate following techniques:
|
||||
* o get ELF object symbol address by calling nlist()
|
||||
* o access virtual memory space from /dev/kmem
|
||||
* o access virtual memory space from /dev/mem
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> //exit
|
||||
#include <linux/a.out.h> //nlist
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <memory.h>
|
||||
|
||||
#define LONG *(volatile unsigned long*)
|
||||
|
||||
/* read from virtual memory */
|
||||
int read_kmem(off_t offset, void* buf, size_t count)
|
||||
{
|
||||
int fd;
|
||||
int n;
|
||||
|
||||
fd = open("/dev/kmem", O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror("open /dev/kmem failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
lseek(fd, offset, SEEK_SET);
|
||||
n = read(fd, buf, count);
|
||||
if (n != count)
|
||||
perror("/dev/kmem read failed");
|
||||
else
|
||||
printf("/dev/kmem read buf = %ld\n", *(unsigned long *)buf);
|
||||
|
||||
close(fd);
|
||||
return n;
|
||||
}
|
||||
|
||||
/* read from physical memory */
|
||||
int read_mem(off_t offset, void* buf, size_t count)
|
||||
{
|
||||
int fd;
|
||||
int n;
|
||||
int page_size;
|
||||
void *map_base;
|
||||
unsigned long value;
|
||||
|
||||
printf("/dev/mem: the offset is %lx\n", offset);
|
||||
|
||||
fd = open("/dev/mem", O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror("open /dev/mem failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(1){
|
||||
page_size = getpagesize();
|
||||
printf("the page size = %d\n", page_size);
|
||||
map_base = mmap(0,page_size,PROT_READ,MAP_SHARED,fd,offset);
|
||||
if (map_base == MAP_FAILED){
|
||||
perror("mmap");
|
||||
exit(1);
|
||||
}
|
||||
value = LONG(map_base);
|
||||
printf("/dev/mem: the value is %ld\n", value);
|
||||
buf = (unsigned long *)map_base;
|
||||
}
|
||||
|
||||
if(0){
|
||||
lseek(fd, offset, SEEK_SET);
|
||||
n = read(fd, buf, count);
|
||||
if (n != count)
|
||||
perror("/dev/mem read failed");
|
||||
else
|
||||
printf("/dev/mem read buf = %ld\n", *(unsigned long *)buf);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return n;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
char addr_str[11]="0x";
|
||||
char var[51];
|
||||
unsigned long addr;
|
||||
unsigned long jiffies;
|
||||
char ch;
|
||||
int r;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr,"usage: %s System.map\n",argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if ((fp = fopen(argv[1],"r")) == NULL) {
|
||||
perror("fopen");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
do {
|
||||
r = fscanf(fp,"%8s %c %50s\n",&addr_str[2],&ch,var); // format of System.map
|
||||
if (strcmp(var,"jiffies")==0)
|
||||
break;
|
||||
} while(r > 0);
|
||||
if (r < 0) {
|
||||
printf("could not find jiffies\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
addr = strtoul(addr_str,NULL,16); //Convert string to unsigned long integer
|
||||
printf("found jiffies at (%s) %08lx\n",addr_str,addr);
|
||||
|
||||
read_kmem(addr, &jiffies, sizeof(jiffies));
|
||||
printf("jiffies=%ld (read from virtual memory)\n\n", jiffies);
|
||||
|
||||
jiffies = 0; //reinit for checking read_mem() below
|
||||
|
||||
read_mem(addr-0xC0000000, &jiffies, sizeof(jiffies));
|
||||
printf("jiffies=%ld (read from physical memory)\n", jiffies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
v2p.o: \
|
||||
/home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/memory/v2p/v2p.c \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/include/linux/kconfig.h \
|
||||
include/linux/autoconf.h include/linux/module.h include/linux/list.h \
|
||||
include/linux/types.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/types.h \
|
||||
include/asm-generic/types.h include/asm-generic/int-ll64.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/bitsperlong.h \
|
||||
include/asm-generic/bitsperlong.h include/linux/posix_types.h \
|
||||
include/linux/stddef.h include/linux/compiler.h \
|
||||
include/linux/compiler-gcc.h include/linux/compiler-gcc4.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/posix_types.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/posix_types_64.h \
|
||||
include/linux/poison.h include/linux/prefetch.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/processor.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/processor-flags.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/vm86.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/ptrace.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/ptrace-abi.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/segment.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/cache.h \
|
||||
include/linux/linkage.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/linkage.h \
|
||||
include/linux/stringify.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/page_types.h \
|
||||
include/linux/const.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/page_64_types.h \
|
||||
include/linux/init.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/math_emu.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/sigcontext.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/current.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/percpu.h \
|
||||
include/linux/kernel.h \
|
||||
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/include/stdarg.h \
|
||||
include/linux/bitops.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/bitops.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/alternative.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/asm.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/cpufeature.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/required-features.h \
|
||||
include/asm-generic/bitops/sched.h include/asm-generic/bitops/hweight.h \
|
||||
include/asm-generic/bitops/fls64.h \
|
||||
include/asm-generic/bitops/ext2-non-atomic.h \
|
||||
include/asm-generic/bitops/le.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/byteorder.h \
|
||||
include/linux/byteorder/little_endian.h include/linux/swab.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/swab.h \
|
||||
include/linux/byteorder/generic.h include/asm-generic/bitops/minix.h \
|
||||
include/linux/log2.h include/linux/typecheck.h include/linux/ratelimit.h \
|
||||
include/linux/param.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/param.h \
|
||||
include/asm-generic/param.h include/linux/dynamic_debug.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/bug.h \
|
||||
include/asm-generic/bug.h include/asm-generic/percpu.h \
|
||||
include/linux/threads.h include/linux/percpu-defs.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/system.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/cmpxchg.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/cmpxchg_64.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/nops.h \
|
||||
include/linux/irqflags.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/irqflags.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/paravirt.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/pgtable_types.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/pgtable_64_types.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/paravirt_types.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/desc_defs.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/kmap_types.h \
|
||||
include/asm-generic/kmap_types.h include/linux/cpumask.h \
|
||||
include/linux/bitmap.h include/linux/string.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/string.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/string_64.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/page.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/page_64.h \
|
||||
include/asm-generic/memory_model.h include/asm-generic/getorder.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/msr.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/msr-index.h \
|
||||
include/linux/ioctl.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/ioctl.h \
|
||||
include/asm-generic/ioctl.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/errno.h \
|
||||
include/asm-generic/errno.h include/asm-generic/errno-base.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/cpumask.h \
|
||||
include/linux/personality.h include/linux/cache.h include/linux/math64.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/div64.h \
|
||||
include/asm-generic/div64.h include/linux/err.h include/linux/stat.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/stat.h \
|
||||
include/linux/time.h include/linux/seqlock.h include/linux/spinlock.h \
|
||||
include/linux/preempt.h include/linux/thread_info.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/thread_info.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/ftrace.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/atomic.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/atomic_64.h \
|
||||
include/asm-generic/atomic-long.h include/linux/bottom_half.h \
|
||||
include/linux/spinlock_types.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/spinlock_types.h \
|
||||
include/linux/lockdep.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/spinlock.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/rwlock.h \
|
||||
include/linux/spinlock_api_smp.h include/linux/kmod.h \
|
||||
include/linux/gfp.h include/linux/mmzone.h include/linux/wait.h \
|
||||
include/linux/numa.h include/linux/nodemask.h \
|
||||
include/linux/pageblock-flags.h include/linux/bounds.h \
|
||||
include/linux/memory_hotplug.h include/linux/notifier.h \
|
||||
include/linux/errno.h include/linux/mutex.h include/linux/rwsem.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/rwsem.h \
|
||||
include/linux/srcu.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/mmzone.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/mmzone_64.h \
|
||||
include/linux/mmdebug.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/smp.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/mpspec.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/mpspec_def.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/x86_init.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/bootparam.h \
|
||||
include/linux/screen_info.h include/linux/apm_bios.h include/linux/edd.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/e820.h \
|
||||
include/linux/ioport.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/ist.h \
|
||||
include/video/edid.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/apic.h \
|
||||
include/linux/delay.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/delay.h \
|
||||
include/linux/pm.h include/linux/workqueue.h include/linux/timer.h \
|
||||
include/linux/ktime.h include/linux/jiffies.h include/linux/timex.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/timex.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/tsc.h \
|
||||
include/linux/debugobjects.h include/linux/completion.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/apicdef.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/fixmap.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/acpi.h \
|
||||
include/acpi/pdc_intel.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/numa.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/numa_64.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/mmu.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/vsyscall.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/idle.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/io_apic.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/irq_vectors.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/sparsemem.h \
|
||||
include/linux/topology.h include/linux/smp.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/topology.h \
|
||||
include/asm-generic/topology.h include/linux/sysctl.h \
|
||||
include/linux/elf.h include/linux/elf-em.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/elf.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/user.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/user_64.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/auxvec.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/vdso.h \
|
||||
include/linux/kobject.h include/linux/sysfs.h include/linux/kref.h \
|
||||
include/linux/moduleparam.h include/linux/tracepoint.h \
|
||||
include/linux/rcupdate.h include/linux/rcutree.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/local.h \
|
||||
include/linux/percpu.h include/linux/slab.h include/linux/slab_def.h \
|
||||
include/linux/kmalloc_sizes.h include/linux/pfn.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/module.h \
|
||||
include/asm-generic/module.h include/trace/events/module.h \
|
||||
include/trace/define_trace.h include/linux/sched.h \
|
||||
include/linux/capability.h include/linux/rbtree.h \
|
||||
include/linux/mm_types.h include/linux/auxvec.h \
|
||||
include/linux/prio_tree.h include/linux/page-debug-flags.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/cputime.h \
|
||||
include/asm-generic/cputime.h include/linux/sem.h include/linux/ipc.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/ipcbuf.h \
|
||||
include/asm-generic/ipcbuf.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/sembuf.h \
|
||||
include/linux/signal.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/signal.h \
|
||||
include/asm-generic/signal-defs.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/siginfo.h \
|
||||
include/asm-generic/siginfo.h include/linux/path.h include/linux/pid.h \
|
||||
include/linux/proportions.h include/linux/percpu_counter.h \
|
||||
include/linux/seccomp.h include/linux/rculist.h include/linux/rtmutex.h \
|
||||
include/linux/plist.h include/linux/resource.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/resource.h \
|
||||
include/asm-generic/resource.h include/linux/hrtimer.h \
|
||||
include/linux/task_io_accounting.h include/linux/latencytop.h \
|
||||
include/linux/cred.h include/linux/key.h include/linux/selinux.h \
|
||||
include/linux/percpu-rwsem.h include/linux/atomic.h include/linux/aio.h \
|
||||
include/linux/aio_abi.h include/linux/uio.h include/linux/mm.h \
|
||||
include/linux/debug_locks.h include/linux/bit_spinlock.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/pgtable.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/pgtable_64.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/pgtable_64_types.h \
|
||||
/usr/src/kernels/2.6.32-573.22.1.el6.x86_64/arch/x86/include/asm/mm_track.h \
|
||||
include/asm-generic/pgtable.h include/linux/page-flags.h \
|
||||
include/linux/huge_mm.h include/linux/vmstat.h
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
obj-m := v2p.o
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
PWD := $(shell pwd)
|
||||
|
||||
all:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*****************************************************************
|
||||
文件名:mem.c
|
||||
输入参数:
|
||||
pid 接收待查询进程的PID
|
||||
va 接收待查询的虚拟地址
|
||||
*****************************************************************/
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
static int pid;
|
||||
static unsigned long va;
|
||||
|
||||
module_param(pid,int,0644);
|
||||
module_param(va,ulong,0644);
|
||||
|
||||
static int find_pgd_init(void)
|
||||
{
|
||||
unsigned long pa = 0;
|
||||
struct task_struct *pcb_tmp = NULL;
|
||||
pgd_t *pgd_tmp = NULL;
|
||||
pud_t *pud_tmp = NULL;
|
||||
pmd_t *pmd_tmp = NULL;
|
||||
pte_t *pte_tmp = NULL;
|
||||
|
||||
printk(KERN_INFO"PAGE_OFFSET = 0x%lx\n",PAGE_OFFSET);
|
||||
printk(KERN_INFO"PGDIR_SHIFT = %d\n",PGDIR_SHIFT);
|
||||
printk(KERN_INFO"PUD_SHIFT = %d\n",PUD_SHIFT);
|
||||
printk(KERN_INFO"PMD_SHIFT = %d\n",PMD_SHIFT);
|
||||
printk(KERN_INFO"PAGE_SHIFT = %d\n",PAGE_SHIFT);
|
||||
|
||||
printk(KERN_INFO"PTRS_PER_PGD = %d\n",PTRS_PER_PGD);
|
||||
printk(KERN_INFO"PTRS_PER_PUD = %d\n",PTRS_PER_PUD);
|
||||
printk(KERN_INFO"PTRS_PER_PMD = %d\n",PTRS_PER_PMD);
|
||||
printk(KERN_INFO"PTRS_PER_PTE = %d\n",PTRS_PER_PTE);
|
||||
|
||||
printk(KERN_INFO"PAGE_MASK = 0x%lx\n",PAGE_MASK);
|
||||
|
||||
if(!(pcb_tmp = find_task_by_pid(pid)))
|
||||
{
|
||||
printk(KERN_INFO"Can't find the task %d .\n",pid);
|
||||
return 0;
|
||||
}
|
||||
printk(KERN_INFO"pgd = 0x%p\n",pcb_tmp->mm->pgd);
|
||||
|
||||
/* 判断给出的地址va是否合法(va<vm_end)*/
|
||||
if(!find_vma(pcb_tmp->mm,va))
|
||||
{
|
||||
printk(KERN_INFO"virt_addr 0x%lx not available.\n",va);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pgd_tmp = pgd_offset(pcb_tmp->mm,va);
|
||||
printk(KERN_INFO"pgd_tmp = 0x%p\n",pgd_tmp);
|
||||
printk(KERN_INFO"pgd_val(*pgd_tmp) = 0x%lx\n",pgd_val(*pgd_tmp));
|
||||
if(pgd_none(*pgd_tmp))
|
||||
{
|
||||
printk(KERN_INFO"Not mapped in pgd.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pud_tmp = pud_offset(pgd_tmp,va);
|
||||
printk(KERN_INFO"pud_tmp = 0x%p\n",pud_tmp);
|
||||
printk(KERN_INFO"pud_val(*pud_tmp) = 0x%lx\n",pud_val(*pud_tmp));
|
||||
if(pud_none(*pud_tmp))
|
||||
{
|
||||
printk(KERN_INFO"Not mapped in pud.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pmd_tmp = pmd_offset(pud_tmp,va);
|
||||
printk(KERN_INFO"pmd_tmp = 0x%p\n",pmd_tmp);
|
||||
printk(KERN_INFO"pmd_val(*pmd_tmp) = 0x%lx\n",pmd_val(*pmd_tmp));
|
||||
if(pmd_none(*pmd_tmp))
|
||||
{
|
||||
printk(KERN_INFO"Not mapped in pmd.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*在这里,把原来的pte_offset_map()改成了pte_offset_kernel*/
|
||||
pte_tmp = pte_offset_kernel(pmd_tmp,va);
|
||||
|
||||
printk(KERN_INFO"pte_tmp = 0x%p\n",pte_tmp);
|
||||
printk(KERN_INFO"pte_val(*pte_tmp) = 0x%lx\n",pte_val(*pte_tmp));
|
||||
if(pte_none(*pte_tmp))
|
||||
{
|
||||
printk(KERN_INFO"Not mapped in pte.\n");
|
||||
return 0;
|
||||
}
|
||||
if(!pte_present(*pte_tmp)){
|
||||
printk(KERN_INFO"pte not in RAM.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pa = (pte_val(*pte_tmp) & PAGE_MASK) | (va & ~PAGE_MASK);
|
||||
printk(KERN_INFO"virt_addr 0x%lx in RAM is 0x%lx t .\n",va,pa);
|
||||
printk(KERN_INFO"contect in 0x%lx is 0x%lx\n", pa, *(unsigned long *)((char *)pa + PAGE_OFFSET));
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void find_pgd_exit(void)
|
||||
{
|
||||
printk(KERN_INFO"Goodbye!\n");
|
||||
|
||||
}
|
||||
|
||||
module_init(find_pgd_init);
|
||||
module_exit(find_pgd_exit);
|
||||
@@ -0,0 +1,21 @@
|
||||
ROOT=$(shell pwd)
|
||||
|
||||
DIRS=list find
|
||||
|
||||
|
||||
all:
|
||||
for i in $(DIRS); do \
|
||||
(cd $$i && echo "making $$i" && $(MAKE) ) || exit 1; \
|
||||
done
|
||||
|
||||
clean:
|
||||
for i in $(DIRS); do \
|
||||
(cd $$i && echo "cleaning $$i" && $(MAKE) clean) || exit 1; \
|
||||
done
|
||||
|
||||
install :
|
||||
# for i in $(DIRS); do \
|
||||
# (cd $$i && echo "install $$i" && $(MAKE) install) || exit 1; \
|
||||
# done
|
||||
cp $(INJECTOR)/memInjector $(BIN)/memInjector
|
||||
cp $(ENGINE)/memoryEngine.ko $(BIN)/memoryEngine.ko
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
obj-m := find_task.o
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
PWD := $(shell pwd)
|
||||
|
||||
all:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*************************************************************************
|
||||
> File Name: process.c
|
||||
> Author: GatieMe
|
||||
> Mail: gatieme@163.com
|
||||
> Created Time: 2016年04月01日 星期五 21时09分29秒
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
|
||||
|
||||
|
||||
//#define METHOD 2
|
||||
static unsigned int METHOD = 1;
|
||||
module_param(METHOD, uint,0400);
|
||||
|
||||
static unsigned int PID = 1;
|
||||
module_param(PID, uint,0400);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void getTaskinfo(struct task_struct *task)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
void findTaskByPid(int pid)
|
||||
{
|
||||
struct task_struct *task = NULL, *pTask = NULL;
|
||||
struct list_head *pos = NULL;
|
||||
char *method = NULL;
|
||||
|
||||
task = &init_task;
|
||||
|
||||
printk(KERN_ALERT"PID\tCOMM\tADDR\n");
|
||||
|
||||
|
||||
switch(METHOD)
|
||||
{
|
||||
case 1 :
|
||||
method = "list_for_each";
|
||||
list_for_each(pos, &task->tasks)
|
||||
{
|
||||
pTask = list_entry(pos, struct task_struct, tasks );
|
||||
if(pTask->pid == (pid_t)pid)
|
||||
{
|
||||
printk(KERN_ALERT "%d\t%s\t%p\n", pTask->pid, pTask->comm, pTask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 2 :
|
||||
method = "for_each_process";
|
||||
for_each_process(task)
|
||||
{
|
||||
if(task->pid == pid)
|
||||
{
|
||||
printk(KERN_ALERT "%d\t%s\t%p\n", task->pid, task->comm, task);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3 :
|
||||
method = "list_for_each_entry";
|
||||
list_for_each_entry(pTask, &task->tasks, tasks)
|
||||
{
|
||||
if(pTask->pid == (pid_t)pid)
|
||||
{
|
||||
printk(KERN_ALERT "%d\t%s\t%p\n", pTask->pid, pTask->comm, pTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
printk("the method is %s", method);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_find_task(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void exit_find_task(void)
|
||||
{
|
||||
printk(KERN_ALERT "GOOD BYE:find_task!!\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
module_init(init_find_taskt);
|
||||
module_exit(exit_find_task);
|
||||
|
||||
MODULE_AUTHOR("gatieme");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,104 @@
|
||||
/*************************************************************************
|
||||
> File Name: process.c
|
||||
> Author: GatieMe
|
||||
> Mail: gatieme@163.com
|
||||
> Created Time: 2016年04月01日 星期五 21时09分29秒
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
|
||||
/*
|
||||
* find_task_by_pid maybe not supported
|
||||
* O(n) is fine :)
|
||||
*/
|
||||
struct task_struct * findTaskByPid(pid_t pid)
|
||||
{
|
||||
struct task_struct *task = NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* show the task info
|
||||
*/
|
||||
void getTaskinfo(struct task_struct *task)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//#define METHOD 2
|
||||
static unsigned int METHOD = 1;
|
||||
module_param(METHOD, uint,0400);
|
||||
|
||||
static unsigned int PID = 1;
|
||||
module_param(PID, uint,0400);
|
||||
static int find_task_init(void)
|
||||
{
|
||||
struct task_struct *task = NULL, *pTask = NULL;
|
||||
struct list_head *pos = NULL;
|
||||
char *method = NULL;
|
||||
|
||||
task = &init_task;
|
||||
|
||||
printk(KERN_ALERT"PID\tCOMM\tADDR\n");
|
||||
|
||||
|
||||
switch(METHOD)
|
||||
{
|
||||
case 1 :
|
||||
method = "list_for_each";
|
||||
list_for_each(pos, &task->tasks)
|
||||
{
|
||||
pTask = list_entry(pos, struct task_struct, tasks );
|
||||
if(pTask->pid == (pid_t)PID)
|
||||
{
|
||||
printk(KERN_ALERT "%d\t%s\t%p\n", pTask->pid, pTask->comm, pTask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 2 :
|
||||
method = "for_each_process";
|
||||
for_each_process(task)
|
||||
{
|
||||
if(task->pid == PID)
|
||||
{
|
||||
printk(KERN_ALERT "%d\t%s\t%p\n", task->pid, task->comm, task);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3 :
|
||||
method = "list_for_each_entry";
|
||||
list_for_each_entry(pTask, &task->tasks, tasks)
|
||||
{
|
||||
if(pTask->pid == PID)
|
||||
{
|
||||
printk(KERN_ALERT "%d\t%s\t%p\n", pTask->pid, pTask->comm, pTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
printk("the method is %s", method);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void find_task_exit(void)
|
||||
{
|
||||
printk(KERN_ALERT "GOOD BYE:find_task!!\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
module_init(find_task_init);
|
||||
module_exit(find_task_exit);
|
||||
|
||||
MODULE_AUTHOR("gatieme");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
obj-m := kernel_thread.o
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
PWD := $(shell pwd)
|
||||
|
||||
all:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*************************************************************************
|
||||
> File Name: process.c
|
||||
> Author: GatieMe
|
||||
> Mail: gatieme@163.com
|
||||
> Created Time: 2016年04月01日 星期五 21时09分29秒
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/pid.h>
|
||||
|
||||
|
||||
|
||||
//#define METHOD 2
|
||||
static unsigned int METHOD = 1;
|
||||
module_param(METHOD, uint,0400);
|
||||
|
||||
static unsigned int PID = 1;
|
||||
module_param(PID, uint,0400);
|
||||
|
||||
|
||||
int kthread_function(void *argc)
|
||||
{
|
||||
printk(KERN_ALERT "in the kernel thread function!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_kernel_thread_pid(void)
|
||||
{
|
||||
pid_t res = -1;
|
||||
struct pid *ktpid = NULL;
|
||||
struct task_struct *task = NULL;
|
||||
|
||||
// create a kernel thread
|
||||
res = kernel_thread(kthread_function, NULL, CLONE_KERNEL);
|
||||
|
||||
// get the pid of the kernel thread you create
|
||||
ktpid = find_get_pid(res);
|
||||
|
||||
// get the task info of the kernel thread
|
||||
task = pid_task(ktpid, PIDTYPE_PID);
|
||||
|
||||
printk(KERN_ALERT "the state of the task is : %ld\n", task->state); //显示任务当前所处的状态
|
||||
|
||||
// get the real PID of the kernel thread
|
||||
printk(KERN_ALERT "the pid of the task is :%d\n", task->pid); //显示任务的进程号
|
||||
|
||||
// get the thread id of the kernel thread
|
||||
printk(KERN_ALERT "the tgid of the task is : %d\n", task->tgid);
|
||||
|
||||
// 显示函数kernel_thread( )函数执行结果
|
||||
printk(KERN_ALERT "the kernel_thread result is : %d\n", res);
|
||||
printk(KERN_ALERT "out pid_task_init.\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int init_kernel_thread(void)
|
||||
{
|
||||
print_kernel_thread_pid( );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exit_kernel_thread(void)
|
||||
{
|
||||
printk(KERN_ALERT "GOOD BYE:kernel_thread!!\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
module_init(init_kernel_thread);
|
||||
module_exit(exit_kernel_thread);
|
||||
|
||||
MODULE_AUTHOR("gatieme");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
obj-m := list_process.o
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
PWD := $(shell pwd)
|
||||
|
||||
all:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*************************************************************************
|
||||
> File Name: process.c
|
||||
> Author: GatieMe
|
||||
> Mail: gatieme@163.com
|
||||
> Created Time: 2016年04月01日 星期五 21时09分29秒
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
|
||||
/*
|
||||
* you can use METHOD to select the function you want to list the process
|
||||
* METHOD = 1 "list_for_each"
|
||||
* METHOD = 2 "for_each_process"
|
||||
* METHOD = 3 "list_for_each_entry"
|
||||
*/
|
||||
static unsigned int METHOD = 1;
|
||||
module_param(METHOD, uint, 0400);
|
||||
|
||||
|
||||
void do_list_process(void)
|
||||
{
|
||||
struct task_struct *task = NULL, *pTask = NULL;
|
||||
struct list_head *pos = 0;
|
||||
int count = 0;
|
||||
char *method = NULL;
|
||||
|
||||
|
||||
count = 0;
|
||||
task = &init_task;
|
||||
printk(KERN_ALERT"PID\tCOMM\n");
|
||||
|
||||
|
||||
switch(METHOD)
|
||||
{
|
||||
case 1 :
|
||||
method = "list_for_each";
|
||||
list_for_each(pos, &task->tasks)
|
||||
{
|
||||
pTask = list_entry(pos, struct task_struct, tasks);
|
||||
count++;
|
||||
printk(KERN_ALERT "%d\t%s\n", pTask->pid, pTask->comm);
|
||||
}
|
||||
|
||||
// because the list of process is an double-linked circular list
|
||||
// we can also list all the process from the current process
|
||||
/*
|
||||
list_for_each(pos, ¤t->children)
|
||||
{
|
||||
pTask = list_entry(pos, struct task_struct, sibling);
|
||||
printk(KERN_ALERT "%d\t%s\n", pTask->pid, pTask->comm);
|
||||
}
|
||||
*/
|
||||
|
||||
break;
|
||||
case 2 :
|
||||
method = "for_each_process";
|
||||
for_each_process(pTask)
|
||||
{
|
||||
count++;
|
||||
printk(KERN_ALERT "%d\t%s\n", pTask->pid, pTask->comm);
|
||||
}
|
||||
break;
|
||||
case 3 :
|
||||
|
||||
method = "list_for_each_entry";
|
||||
list_for_each_entry(pTask, &task->tasks, tasks)
|
||||
{
|
||||
count++;
|
||||
printk(KERN_ALERT "%d\t%s\n", pTask->pid, pTask->comm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
printk(KERN_ALERT "The method is %s\n", method);
|
||||
printk(KERN_ALERT "there are %d process in your system now...\n", count);
|
||||
printk(KERN_ALERT "current : %d\t%s\n", current->pid, current->comm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int init_list_process(void)
|
||||
{
|
||||
// list all the process of you system
|
||||
do_list_process( );
|
||||
}
|
||||
|
||||
static void exit_list_process(void)
|
||||
{
|
||||
printk(KERN_ALERT "GOOD BYE--list process!!\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
module_init(init_list_process);
|
||||
module_exit(exit_list_process);
|
||||
|
||||
|
||||
MODULE_AUTHOR("gatieme");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,171 @@
|
||||
| 日期 | 内核版本 | 架构| 作者 | GitHub| CSDN |
|
||||
| ------------- |:-------------:|:-------------:|:-------------:|:-------------:|:-------------:|
|
||||
| 2016-05-12 | [Linux-4.5](http://lxr.free-electrons.com/source/?v=4.5) | X86 & arm | [gatieme](http://blog.csdn.net/gatieme) | [LinuxDeviceDrivers](https://github.com/gatieme/LDD-LinuxDeviceDrivers) | [Linux-进程管理与调度](http://blog.csdn.net/gatieme/article/category/6225543) |
|
||||
|
||||
>Linux Namespaces机制提供一种资源隔离方案。
|
||||
|
||||
|
||||
PID,IPC,Network等系统资源不再是全局性的,而是属于特定的Namespace。每个Namespace里面的资源对其他Namespace都是透明的。要创建新的Namespace,只需要在调用clone时指定相应的flag。Linux Namespaces机制为实现基于容器的虚拟化技术提供了很好的基础,LXC(Linux containers)就是利用这一特性实现了资源的隔离。不同Container内的进程属于不同的Namespace,彼此透明,互不干扰。下面我们就从clone系统调用的flag出发,来介绍各个Namespace。
|
||||
命名空间提供了虚拟化的一种轻量级形式,使得我们可以从不同的方面来查看运行系统的全局属性。该机制类似于Solaris中的zone或 FreeBSD中的jail。对该概念做一般概述之后,我将讨论命名空间框架所提供的基础设施。
|
||||
|
||||
#命名空间概念
|
||||
-------
|
||||
|
||||
传统上,在Linux以及其他衍生的UNIX变体中,许多资源是全局管理的。
|
||||
|
||||
例如,系统中的所有进程按照惯例是通过PID标识的,这意味着内核必须管理一个**全局的PID列表**。而且,所有调用者通过uname系统调用返回的系统相关信息(包括系统名称和有关内核的一些信息)都是相同的。用户ID的管理方式类似,即各个用户是通过一个全局唯一的UID号标识。
|
||||
|
||||
全局ID使得内核可以有选择地允许或拒绝某些特权。虽然UID为0的root用户基本上允许做任何事,但其他用户ID则会受到限制。例如UID为n 的用户,不允许杀死属于用户m的进程(m≠ n)。但这不能防止用户看到彼此,即用户n可以看到另一个用户m也在计算机上活动。只要用户只能操纵他们自己的进程,这就没什么问题,因为没有理由不允许用户看到其他用户的进程。
|
||||
|
||||
但有些情况下,这种效果可能是不想要的。如果提供Web主机的供应商打算向用户提供Linux计算机的全部访问权限,包括root权限在内。传统上,这需要为每个用户准备一台计算机,代价太高。使用KVM或VMWare提供的虚拟化环境是一种解决问题的方法,但资源分配做得不是非常好。计算机的各个用户都需要一个独立的内核,以及一份完全安装好的配套的用户层应用。
|
||||
|
||||
**命名空间**提供了一种不同的解决方案,所需资源较少。在虚拟化的系统中,一台物理计算机可以运行多个内核,可能是并行的多个不同的操作系统。而命名空间则只使用一个内核在一台物理计算机上运作,前述的所有全局资源都通过命名空间抽象起来。这使得可以将一组进程放置到容器中,各个容器彼此隔离。隔离可以使容器的成员与其他容器毫无关系。但也可以通过允许容器进行一定的共享,来降低容器之间的分隔。例如,容器可以设置为使用自身的PID集合,但仍然与其他容器共享部分文件系统。
|
||||
|
||||
本质上,命名空间建立了系统的不同视图。此前的每一项全局资源都必须包装到容器数据结构中,只有资源和包含资源的命名空间构成的二元组仍然是全局唯一的。虽然在给定容器内部资源是自足的,但无法提供在容器外部具有唯一性的ID。
|
||||
|
||||
考虑系统上有3个不同命名空间的情况。命名空间可以组织为层次,我会在这里讨论这种情况。一个命名空间是父命名空间,衍生了两个子命名空间。假定容器用于虚拟主机配置中,其中的每个容器必须看起来像是单独的一台Linux计算机。因此其中每一个都有自身的init进程,PID为0,其他进程的PID 以递增次序分配。两个子命名空间都有PID为0的init进程,以及PID分别为2和3的两个进程。由于相同的PID在系统中出现多次,PID号不是全局唯一的。
|
||||
|
||||
|
||||
|
||||
虽然子容器不了解系统中的其他容器,但父容器知道子命名空间的存在,也可以看到其中执行的所有进程。图中子容器的进程映射到父容器中,PID为4到 9。尽管系统上有9个进程,但却需要15个PID来表示,因为一个进程可以关联到多个PID。至于哪个PID是"正确"的,则依赖于具体的上下文。
|
||||
|
||||
如果命名空间包含的是比较简单的量,也可以是非层次的,例如下文讨论的UTS命名空间。在这种情况下,父子命名空间之间没有联系。
|
||||
请注意,Linux系统对简单形式的命名空间的支持已经有很长一段时间了,主要是chroot系统调用。该方法可以将进程限制到文件系统的某一部分,因而是一种简单的命名空间机制。但真正的命名空间能够控制的功能远远超过文件系统视图。
|
||||
|
||||
|
||||
#Linux内核命名空间描述
|
||||
-------
|
||||
|
||||
在Linux内核中提供了多个namespace,其中包括fs (mount), uts, network, sysvipc, 等。一个进程可以属于多个namesapce,既然namespace和进程相关,那么在task_struct结构体中就会包含和namespace相关联的变量。在task_struct 结构中有一个指向namespace结构体的指针nsproxy。
|
||||
```c
|
||||
struct task_struct
|
||||
{
|
||||
……..
|
||||
/* namespaces */
|
||||
struct nsproxy *nsproxy;
|
||||
…….
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
再看一下[nsproxy](http://lxr.free-electrons.com/source/include/linux/nsproxy.h#L29)是如何定义的,在[include/linux/nsproxy.h](http://lxr.free-electrons.com/source/include/linux/nsproxy.h)文件中,这里一共定义了5个各自的命名空间结构体,在该结构体中定义了5个指向各个类型namespace的指针,由于多个进程可以使用同一个namespace,所以nsproxy可以共享使用,count字段是该结构的引用计数。
|
||||
|
||||
```c
|
||||
/* 'count' is the number of tasks holding a reference.
|
||||
* The count for each namespace, then, will be the number
|
||||
* of nsproxies pointing to it, not the number of tasks.
|
||||
* The nsproxy is shared by tasks which share all namespaces.
|
||||
* As soon as a single namespace is cloned or unshared, the
|
||||
* nsproxy is copied
|
||||
*/
|
||||
struct nsproxy
|
||||
{
|
||||
atomic_t count;
|
||||
struct uts_namespace *uts_ns;
|
||||
struct ipc_namespace *ipc_ns;
|
||||
struct mnt_namespace *mnt_ns;
|
||||
struct pid_namespace *pid_ns_for_children;
|
||||
struct net *net_ns;
|
||||
};
|
||||
```
|
||||
1. UTS命名空间包含了运行内核的名称、版本、底层体系结构类型等信息。UTS是UNIX Timesharing System的简称。
|
||||
|
||||
2. 保存在struct ipc_namespace中的所有与进程间通信(IPC)有关的信息。
|
||||
|
||||
3. 已经装载的文件系统的视图,在struct mnt_namespace中给出。
|
||||
|
||||
4. 有关进程ID的信息,由struct pid_namespace提供。
|
||||
|
||||
5. struct net_ns包含所有网络相关的命名空间参数。
|
||||
|
||||
系统中有一个默认的`nsproxy`,[init_nsproxy](http://lxr.free-electrons.com/source/include/linux/init_task.h#L232),该结构在task初始化是也会被初始,定义在[include/linux/init_task.h](http://lxr.free-electrons.com/source/include/linux/init_task.h#L190)
|
||||
|
||||
```c
|
||||
#define INIT_TASK(tsk) \
|
||||
{
|
||||
……..
|
||||
.nsproxy = &init_nsproxy,
|
||||
……..
|
||||
}
|
||||
```
|
||||
|
||||
其中[init_nsproxy](http://lxr.free-electrons.com/source/kernel/nsproxy.c#L31)的定义为:
|
||||
|
||||
```
|
||||
struct nsproxy init_nsproxy = {
|
||||
.count = ATOMIC_INIT(1),
|
||||
.uts_ns = &init_uts_ns,
|
||||
#if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
|
||||
.ipc_ns = &init_ipc_ns,
|
||||
#endif
|
||||
.mnt_ns = NULL,
|
||||
.pid_ns_for_children = &init_pid_ns,
|
||||
#ifdef CONFIG_NET
|
||||
.net_ns = &init_net,
|
||||
#endif
|
||||
};
|
||||
```
|
||||
对于.mnt_ns没有进行初始化,其余的namespace都进行了系统默认初始
|
||||
|
||||
|
||||
#命名空间的创建
|
||||
-------
|
||||
|
||||
新的命名空间可以用下面两种方法创建。
|
||||
|
||||
1. 在用fork或clone系统调用创建新进程时,有特定的选项可以控制是与父进程共享命名空间,还是建立新的命名空间。
|
||||
|
||||
2. unshare系统调用将进程的某些部分从父进程分离,其中也包括命名空间。更多信息请参见手册页unshare(2)。
|
||||
|
||||
在进程已经使用上述的两种机制之一从父进程命名空间分离后,从该进程的角度来看,改变全局属性不会传播到父进程命名空间,而父进程的修改也不会传播到子进 程,至少对于简单的量是这样。而对于文件系统来说,情况就比较复杂,其中的共享机制非常强大,带来了大量的可能性。
|
||||
|
||||
命名空间的实现需要两个部分:每个子系统的命名空间结构,将此前所有的全局组件包装到命名空间中;将给定进程关联到所属各个命名空间的机制。
|
||||
|
||||
在用fork或clone系统调用创建新进程时,有特定的选项可以控制是与父进程共享命名空间,还是建立新的命名空间。这些选项如下
|
||||
|
||||
* CLONE_NEWPID 进程命名空间。空间内的PID 是独立分配的,意思就是命名空间内的虚拟 PID 可能会与命名空间外的 PID 相冲突,于是命名空间内的 PID 映射到命名空间外时会使用另外一个 PID。比如说,命名空间内第一个 PID 为1,而在命名空间外就是该 PID 已被 init 进程所使用。
|
||||
|
||||
* CLONE_NEWIPC 进程间通信(IPC)的命名空间,可以将 SystemV 的 IPC 和 POSIX 的消息队列独立出来。
|
||||
|
||||
* CLONE_NEWNET 网络命名空间,用于隔离网络资源(/proc/net、IP 地址、网卡、路由等)。后台进程可以运行在不同命名空间内的相同端口上,用户还可以虚拟出一块网卡。
|
||||
|
||||
* CLONE_NEWNS 挂载命名空间,进程运行时可以将挂载点与系统分离,使用这个功能时,我们可以达到 chroot 的功能,而在安全性方面比 chroot 更高。
|
||||
|
||||
* CLONE_NEWUTS UTS 命名空间,主要目的是独立出主机名和网络信息服务(NIS)。
|
||||
|
||||
* CLONE_NEWUSER 用户命名空间,同进程 ID 一样,用户 ID 和组 ID 在命名空间内外是不一样的,并且在不同命名空间内可以存在相同的 ID。
|
||||
|
||||
|
||||
##PID Namespace
|
||||
-------
|
||||
|
||||
当调用clone时,设定了CLONE_NEWPID,就会创建一个新的PID Namespace,clone出来的新进程将成为Namespace里的第一个进程。一个PID Namespace为进程提供了一个独立的PID环境,PID Namespace内的PID将从1开始,在Namespace内调用fork,vfork或clone都将产生一个在该Namespace内独立的PID。新创建的Namespace里的第一个进程在该Namespace内的PID将为1,就像一个独立的系统里的init进程一样。该Namespace内的孤儿进程都将以该进程为父进程,当该进程被结束时,该Namespace内所有的进程都会被结束。PID Namespace是层次性,新创建的Namespace将会是创建该Namespace的进程属于的Namespace的子Namespace。子Namespace中的进程对于父Namespace是可见的,一个进程将拥有不止一个PID,而是在所在的Namespace以及所有直系祖先Namespace中都将有一个PID。系统启动时,内核将创建一个默认的PID Namespace,该Namespace是所有以后创建的Namespace的祖先,因此系统所有的进程在该Namespace都是可见的。
|
||||
|
||||
##IPC Namespace
|
||||
-------
|
||||
|
||||
当调用clone时,设定了CLONE_NEWIPC,就会创建一个新的IPC Namespace,clone出来的进程将成为Namespace里的第一个进程。一个IPC Namespace有一组System V IPC objects 标识符构成,这标识符有IPC相关的系统调用创建。在一个IPC Namespace里面创建的IPC object对该Namespace内的所有进程可见,但是对其他Namespace不可见,这样就使得不同Namespace之间的进程不能直接通信,就像是在不同的系统里一样。当一个IPC Namespace被销毁,该Namespace内的所有IPC object会被内核自动销毁。
|
||||
PID Namespace和IPC Namespace可以组合起来一起使用,只需在调用clone时,同时指定CLONE_NEWPID和CLONE_NEWIPC,这样新创建的Namespace既是一个独立的PID空间又是一个独立的IPC空间。不同Namespace的进程彼此不可见,也不能互相通信,这样就实现了进程间的隔离。
|
||||
|
||||
##mount Namespace
|
||||
-------
|
||||
|
||||
当调用clone时,设定了CLONE_NEWNS,就会创建一个新的mount Namespace。每个进程都存在于一个mount Namespace里面,mount Namespace为进程提供了一个文件层次视图。如果不设定这个flag,子进程和父进程将共享一个mount Namespace,其后子进程调用mount或umount将会影响到所有该Namespace内的进程。如果子进程在一个独立的mount Namespace里面,就可以调用mount或umount建立一份新的文件层次视图。该flag配合pivot_root系统调用,可以为进程创建一个独立的目录空间。
|
||||
|
||||
##Network Namespace
|
||||
-------
|
||||
|
||||
当调用clone时,设定了CLONE_NEWNET,就会创建一个新的Network Namespace。一个Network Namespace为进程提供了一个完全独立的网络协议栈的视图。包括网络设备接口,IPv4和IPv6协议栈,IP路由表,防火墙规则,sockets等等。一个Network Namespace提供了一份独立的网络环境,就跟一个独立的系统一样。一个物理设备只能存在于一个Network Namespace中,可以从一个Namespace移动另一个Namespace中。虚拟网络设备(virtual network device)提供了一种类似管道的抽象,可以在不同的Namespace之间建立隧道。利用虚拟化网络设备,可以建立到其他Namespace中的物理设备的桥接。当一个Network Namespace被销毁时,物理设备会被自动移回init Network Namespace,即系统最开始的Namespace。
|
||||
|
||||
##UTS Namespace
|
||||
-------
|
||||
|
||||
当调用clone时,设定了CLONE_NEWUTS,就会创建一个新的UTS Namespace。一个UTS Namespace就是一组被uname返回的标识符。新的UTS Namespace中的标识符通过复制调用进程所属的Namespace的标识符来初始化。Clone出来的进程可以通过相关系统调用改变这些标识符,比如调用sethostname来改变该Namespace的hostname。这一改变对该Namespace内的所有进程可见。CLONE_NEWUTS和CLONE_NEWNET一起使用,可以虚拟出一个有独立主机名和网络空间的环境,就跟网络上一台独立的主机一样。
|
||||
以上所有clone flag都可以一起使用,为进程提供了一个独立的运行环境。LXC正是通过clone时设定这些flag,为进程创建一个有独立PID,IPC,FS,Network,UTS空间的container。一个container就是一个虚拟的运行环境,对container里的进程是透明的,它会以为自己是直接在一个系统上运行的。一个container就像传统虚拟化技术里面的一台安装了OS的虚拟机,但是开销更小,部署更为便捷。
|
||||
Linux Namespaces机制本身就是为了实现 container based virtualizaiton开发的。它提供了一套轻量级、高效率的系统资源隔离方案,远比传统的虚拟化技术开销小,不过它也不是完美的,它为内核的开发带来了更多的复杂性,它在隔离性和容错性上跟传统的虚拟化技术比也还有差距。
|
||||
|
||||
##[user_namespace](http://lxr.free-electrons.com/source/include/linux/user_namespace.h#L25)
|
||||
-------
|
||||
|
||||
CLONE_NEWUSER指定子进程拥有新的用户空间
|
||||
|
||||
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 31 KiB |