From e27e7ef9ce3b5d57090db94ca54655baa2a9641d Mon Sep 17 00:00:00 2001 From: gatieme Date: Fri, 29 Jul 2016 23:53:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=9A=84proc=5Ftest=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8=E5=8C=85=E6=8B=AC=E5=8F=AA=E8=AF=BBproc=5Fentry,=20?= =?UTF-8?q?=E5=8F=AA=E5=86=99proc=5Fentry=E5=92=8C=E5=8F=AF=E8=AF=BB?= =?UTF-8?q?=E5=86=99proc=5Fentry...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 +- Makefile.multi => study/driver/Makefile.multi | 0 .../driver/Makefile.simple | 7 + study/driver/hello_dev/Makefile | 96 ++++- study/driver/hello_dev/hello.c | 20 +- .../driver/hello_proc/.tmp_versions/hello.mod | 2 - study/driver/hello_proc/Makefile | 97 ++++- study/driver/hello_proc/hello.c | 81 ++-- study/proc/proc_final/Makefile | 87 ++++ study/proc/proc_final/common.h | 379 ++++++++++++++++++ study/proc/proc_final/config.h | 76 ++++ study/proc/proc_final/main.c | 237 +++++++++++ study/proc/proc_final/main.h | 34 ++ study/proc/proc_final/ro.c | 75 ++++ study/proc/proc_final/rw.c | 87 ++++ study/proc/proc_final/wo.c | 60 +++ study/proc/seq_file_exam/seq_file_exam.c | 2 +- 17 files changed, 1269 insertions(+), 73 deletions(-) rename Makefile.multi => study/driver/Makefile.multi (100%) rename Makefile.simple => study/driver/Makefile.simple (82%) delete mode 100644 study/driver/hello_proc/.tmp_versions/hello.mod create mode 100644 study/proc/proc_final/Makefile create mode 100644 study/proc/proc_final/common.h create mode 100644 study/proc/proc_final/config.h create mode 100644 study/proc/proc_final/main.c create mode 100644 study/proc/proc_final/main.h create mode 100644 study/proc/proc_final/ro.c create mode 100644 study/proc/proc_final/rw.c create mode 100644 study/proc/proc_final/wo.c diff --git a/Makefile b/Makefile index d9c6044..95b75fb 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ all:github -COMMIT="更新了CFS调度器类的学习实例和博客信息..." +COMMIT="测试的proc_test驱动包括只读proc_entry, 只写proc_entry和可读写proc_entry..." .PHONY : github github: diff --git a/Makefile.multi b/study/driver/Makefile.multi similarity index 100% rename from Makefile.multi rename to study/driver/Makefile.multi diff --git a/Makefile.simple b/study/driver/Makefile.simple similarity index 82% rename from Makefile.simple rename to study/driver/Makefile.simple index bfcd64e..5a7818f 100644 --- a/Makefile.simple +++ b/study/driver/Makefile.simple @@ -17,6 +17,13 @@ ROOT=.. #PLATFORM=$(shell $(ROOT)/systype.sh) #include $(ROOT)/Make.defines.$(PLATFORM) +# my driver description +DRIVER_VERSION := "1.0.0" +DRIVER_AUTHOR := "Gatieme @ AderStep Inc..." +DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices" +DRIVER_LICENSE := "Dual BSD/GPL" + + MODULE_NAME := print_vmarea ifneq ($(KERNELRELEASE),) diff --git a/study/driver/hello_dev/Makefile b/study/driver/hello_dev/Makefile index e060618..807729b 100644 --- a/study/driver/hello_dev/Makefile +++ b/study/driver/hello_dev/Makefile @@ -1,18 +1,78 @@ -ifneq ($(KERNELRELEASE),) - -obj-m := hello.o - -else - -KERNELDIR ?= /lib/modules/$(shell uname -r)/build - -PWD := $(shell pwd) - -all: - make -C $(KERNELDIR) M=$(PWD) modules - -clean: - make -C $(KERNELDIR) M=$(PWD) clean - - -endif +# ------------------------------------------------------------------------------ +# +# Makefile for the LDD-LinuxDeviceDrivers. +# +# Author: gatieme +# Create: 2016-07-29 15:50:46 +# Last modified: 2016-07-29 16:10:29 +# Description: +# This program is loaded as a kernel(v2.6.18 or later) module. +# Use "make install" to load it into kernel. +# Use "make remove" to remove the module out of kernel. +# +# ------------------------------------------------------------------------------ + + +ROOT=.. +#PLATFORM=$(shell $(ROOT)/systype.sh) +#include $(ROOT)/Make.defines.$(PLATFORM) + +# my driver description +DRIVER_VERSION := "1.0.0" +DRIVER_AUTHOR := "Gatieme @ AderStep Inc..." +DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices" +DRIVER_LICENSE := "Dual BSD/GPL" + + +MODULE_NAME := hello + +ifneq ($(KERNELRELEASE),) + +#CFG_FLAGS += -O2 -I./ +#EXTRA_CFLAGS += $(C_FLAGS) $(CFG_INC) $(CFG_INC) + + + +obj-m := $(MODULE_NAME).o #print_vmarea.o + +else + +KERNELDIR ?= /lib/modules/$(shell uname -r)/build + +PWD := $(shell pwd) + +modules: + make -C $(KERNELDIR) M=$(PWD) modules + +modules_install: + make -C $(KERNELDIR) M=$(PWD) modules_install + + + +insmod: + sudo insmod $(MODULE_NAME).ko + +reinsmod: + sudo rmmod $(MODULE_NAME) + sudo insmod $(MODULE_NAME).ko + +github: + cd $(ROOT) && make github + +rmmod: + sudo rmmod $(MODULE_NAME) + +test : + sudo ../injector/memInjector -l stack -m random -t word_0 --time 1 --timeout 3 -p 1 + +clean: + make -C $(KERNELDIR) M=$(PWD) clean + rm -f modules.order Module.symvers Module.markers + +.PHNOY: + modules modules_install clean + + + +endif + diff --git a/study/driver/hello_dev/hello.c b/study/driver/hello_dev/hello.c index 14e5d38..3fcd6f3 100644 --- a/study/driver/hello_dev/hello.c +++ b/study/driver/hello_dev/hello.c @@ -5,7 +5,11 @@ #include -static ssize_t hello_read(struct file * file, char * buf, size_t count, loff_t *ppos) +static ssize_t hello_read( + struct file * file, + char * buf, + size_t count, + loff_t *ppos) { char *hello_str = "Hello, world!\n"; @@ -64,7 +68,7 @@ static struct miscdevice hello_dev = * What functions to call when a program performs file * operations on the device. */ - &hello_fops + &hello_fops, }; @@ -79,8 +83,11 @@ static int __init hello_init(void) ret = misc_register(&hello_dev); if (ret != 0) { - printk(KERN_ERR - "Unable to register \"Hello, world!\" misc devicen"); + printk(KERN_ERR "Unable to register \"Hello, world!\" misc devicen"); + } + else + { + printk(KERN_INFO "register \"Hello World!\" misc devicen...\n"); } return ret; @@ -91,6 +98,7 @@ module_init(hello_init); static void __exit hello_exit(void) { misc_deregister(&hello_dev); + printk(KERN_INFO "deregister \"Hello World!\" misc devicen...\n"); } module_exit(hello_exit); @@ -106,7 +114,3 @@ MODULE_VERSION(DRIVER_VERSION); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE(DRIVER_LICENSE); - - -module_init(globalmem_init); -module_exit(globalmem_exit); diff --git a/study/driver/hello_proc/.tmp_versions/hello.mod b/study/driver/hello_proc/.tmp_versions/hello.mod deleted file mode 100644 index a2fb5b6..0000000 --- a/study/driver/hello_proc/.tmp_versions/hello.mod +++ /dev/null @@ -1,2 +0,0 @@ -/home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/hello/hello.ko -/home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/hello/hello.o diff --git a/study/driver/hello_proc/Makefile b/study/driver/hello_proc/Makefile index c3bf825..807729b 100644 --- a/study/driver/hello_proc/Makefile +++ b/study/driver/hello_proc/Makefile @@ -1,19 +1,78 @@ -ifneq ($(KERNELRELEASE),) - -obj-m := hello.o - -else - -#KERNELDIR ?= /lib/modules/$(shell uname -r)/build -KERNELDIR ?= /usr/src/linux-headers-3.14.0 - -PWD := $(shell pwd) - -all: - make -C $(KERNELDIR) M=$(PWD) modules - -clean: - make -C $(KERNELDIR) M=$(PWD) clean - - -endif +# ------------------------------------------------------------------------------ +# +# Makefile for the LDD-LinuxDeviceDrivers. +# +# Author: gatieme +# Create: 2016-07-29 15:50:46 +# Last modified: 2016-07-29 16:10:29 +# Description: +# This program is loaded as a kernel(v2.6.18 or later) module. +# Use "make install" to load it into kernel. +# Use "make remove" to remove the module out of kernel. +# +# ------------------------------------------------------------------------------ + + +ROOT=.. +#PLATFORM=$(shell $(ROOT)/systype.sh) +#include $(ROOT)/Make.defines.$(PLATFORM) + +# my driver description +DRIVER_VERSION := "1.0.0" +DRIVER_AUTHOR := "Gatieme @ AderStep Inc..." +DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices" +DRIVER_LICENSE := "Dual BSD/GPL" + + +MODULE_NAME := hello + +ifneq ($(KERNELRELEASE),) + +#CFG_FLAGS += -O2 -I./ +#EXTRA_CFLAGS += $(C_FLAGS) $(CFG_INC) $(CFG_INC) + + + +obj-m := $(MODULE_NAME).o #print_vmarea.o + +else + +KERNELDIR ?= /lib/modules/$(shell uname -r)/build + +PWD := $(shell pwd) + +modules: + make -C $(KERNELDIR) M=$(PWD) modules + +modules_install: + make -C $(KERNELDIR) M=$(PWD) modules_install + + + +insmod: + sudo insmod $(MODULE_NAME).ko + +reinsmod: + sudo rmmod $(MODULE_NAME) + sudo insmod $(MODULE_NAME).ko + +github: + cd $(ROOT) && make github + +rmmod: + sudo rmmod $(MODULE_NAME) + +test : + sudo ../injector/memInjector -l stack -m random -t word_0 --time 1 --timeout 3 -p 1 + +clean: + make -C $(KERNELDIR) M=$(PWD) clean + rm -f modules.order Module.symvers Module.markers + +.PHNOY: + modules modules_install clean + + + +endif + diff --git a/study/driver/hello_proc/hello.c b/study/driver/hello_proc/hello.c index 2dcb60c..ea52f73 100644 --- a/study/driver/hello_proc/hello.c +++ b/study/driver/hello_proc/hello.c @@ -1,43 +1,76 @@ -#include -#include +/* + * "Hello, world!" minimal kernel module - /proc version + * + * Valerie Henson + * + */ -MODULE_LICENSE("Dual BSD/GPL"); +#include +#include +#include /* - * print the module information + * Write "Hello, world!" to the buffer passed through the /proc file. */ -static void print_module(void) + +static int +hello_read_proc(char *buffer, char **start, off_t offset, int size, int *eof, + void *data) { - struct module *mod; + char *hello_str = "Hello, world!\n"; + int len = strlen(hello_str); /* Don't include the null byte. */ + /* + * We only support reading the whole string at once. + */ + if (size < len) + return -EINVAL; + /* + * If file position is non-zero, then assume the string has + * been read and indicate there is no more data to be read. + */ + if (offset != 0) + return 0; + /* + * We know the buffer is big enough to hold the string. + */ + strcpy(buffer, hello_str); + /* + * Signal EOF. + */ + *eof = 1; - printk(KERN_ALERT "this module: %p==%p\n", &__this_module, THIS_MODULE); - printk(KERN_ALERT "module state: %d\n", THIS_MODULE->state); - printk(KERN_ALERT "module name: %s\n", THIS_MODULE->name); + return len; - list_for_each_entry(mod, *(&THIS_MODULE->list.prev), list); - printk(KERN_ALERT "module name: %s\n", mod->name); - printk(KERN_ALERT "module state: %d\n", THIS_MODULE->state); } - -static int hello_init(void) +static int __init +hello_init(void) { - print_module( ); - - printk(KERN_ALERT "run in cpu %d\n", get_cpu()); - - printk(KERN_ALERT "PAGE_OFFSET : 0x%lx, TASK_SIZE : 0x%lx", PAGE_OFFSET, TASK_SIZE); - + /* + * Create an entry in /proc named "hello_world" that calls + * hello_read_proc() when the file is read. + */ + if (create_proc_read_entry("hello_world", 0, NULL, hello_read_proc, + NULL) == 0) { + printk(KERN_ERR + "Unable to register \"Hello, world!\" proc file\n"); + return -ENOMEM; + } return 0; } +module_init(hello_init); - -static void hello_exit(void) +static void __exit +hello_exit(void) { + remove_proc_entry("hello_world", NULL); } - -module_init(hello_init); module_exit(hello_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Valerie Henson "); +MODULE_DESCRIPTION("\"Hello, world!\" minimal module"); +MODULE_VERSION("proc"); \ No newline at end of file diff --git a/study/proc/proc_final/Makefile b/study/proc/proc_final/Makefile new file mode 100644 index 0000000..b7839da --- /dev/null +++ b/study/proc/proc_final/Makefile @@ -0,0 +1,87 @@ +# ------------------------------------------------------------------------------ +# +# Makefile for the LDD-LinuxDeviceDrivers. +# +# Author: gatieme +# Create: 2016-07-29 15:50:46 +# Last modified: 2016-07-29 16:10:29 +# Description: +# This program is loaded as a kernel(v2.6.18 or later) module. +# Use "make install" to load it into kernel. +# Use "make remove" to remove the module out of kernel. +# +# ------------------------------------------------------------------------------ + + +ROOT=.. +#PLATFORM=$(shell $(ROOT)/systype.sh) +#include $(ROOT)/Make.defines.$(PLATFORM) + +# my driver description +DRIVER_VERSION := "1.0.0" +DRIVER_AUTHOR := "Gatieme @ AderStep Inc..." +DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices" +DRIVER_LICENSE := "Dual BSD/GPL" + + + +MODULE_NAME := proc-test + +ifneq ($(KERNELRELEASE),) + +#CFG_FLAGS += -O2 -I./ +#EXTRA_CFLAGS += $(C_FLAGS) $(CFG_INC) $(CFG_INC) + + +#MODULE_NAME := proc-test + +RESMAIN_CORE_OBJS := main.o +RESMAIN_GLUE_OBJS := ro.o wo.o rw.o + + + +proc-test-objs := $(RESMAIN_GLUE_OBJS) $(RESMAIN_CORE_OBJS) +obj-m := $(MODULE_NAME).o #proc-test.o + +else + +#MODULE_NAME := proc-test +KERNELDIR ?= /lib/modules/$(shell uname -r)/build +#KERNELDIR ?= /home/gatieme/Work/Kernel/ +PWD := $(shell pwd) + +modules: + make -C $(KERNELDIR) M=$(PWD) modules + +modules_install: + make -C $(KERNELDIR) M=$(PWD) modules_install + + + +insmod: + sudo insmod $(MODULE_NAME).ko + +reinsmod: + sudo rmmod $(MODULE_NAME) + sudo insmod $(MODULE_NAME).ko + +github: + cd $(ROOT) && make github + +rmmod: + sudo rmmod $(MODULE_NAME) + +test : + sudo ../injector/memInjector -l stack -m random -t word_0 --time 1 --timeout 3 -p 1 + +clean: + make -C $(KERNELDIR) M=$(PWD) clean + rm -f modules.order Module.symvers Module.markers + +.PHNOY: + modules modules_install clean + + + +endif + diff --git a/study/proc/proc_final/common.h b/study/proc/proc_final/common.h new file mode 100644 index 0000000..f86271f --- /dev/null +++ b/study/proc/proc_final/common.h @@ -0,0 +1,379 @@ +/* +* Author: HIT CS HDMC team. +* Last modified by zhaozhilong: 2010-1-14 +*/ +#ifndef __COMMON_H_INCLUDE__ +#define __COMMON_H_INCLUDE__ + +#ifdef __KERNEL__ /* in kernel modules */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#else + +#ifdef __cplusplus + + #include + #include + #include + +#else #ifndef __cplusplus + //C header files + #include + #include + #include + +#endif // #endif ifdef __cplusplus + +#endif + + + + +/// 当前字符是数字 +#define IsDigit(c) (c >= '0' && c <= '9') + +/// 当前字符是8进制数据 +#define IsOctDigit(c) (c >= '0' && c <= '7') + +/// 当前字符是16进制数据 +#define IsHexDigit(c) (IsDigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) + +/// 当前字符是字母或者_ +#define IsLetter(c) ((c >= 'a' && c <= 'z') || (c == '_') || (c >= 'A' && c <= 'Z')) + +/// 当前自负是否满足C的变量命名规则 +#define IsLetterOrDigit(c) (IsLetter(c) || IsDigit(c)) +#define IsIdentifier IsLetterOrDigit + +/// 当前字符是空白字符 +#define IsSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r') + + + +/// 取出当前信息的高4位 +#define HIGH_4BIT(v) ((v) >> (8 * sizeof(int) - 4) & 0x0f) +/// 取出当前信息的高3位 +#define HIGH_3BIT(v) ((v) >> (8 * sizeof(int) - 3) & 0x07) +/// 取出当前信息的高1位 +#define HIGH_1BIT(v) ((v) >> (8 * sizeof(int) - 1) & 0x01) +#define ALIGN(size, align) ((size + align - 1) & (~(align - 1))) + +#define BitGet(number, pos) ((number) >> (pos) & 1) /// 用宏得到某数的某位 +#define BitSet(number, pos) ((number) |= 1 << (pos)) /// 把某位置1 +#define BitClr(number, pos) ((number) &= ~(1 << (pos))) /// 把某位清0 +#define BitCpl(number, pos) ((number) ^= 1 << (pos)) /// 把number的POS位取反 + + +///03: 得到指定地址上的一个字节或字 +#define MEM_B(x) (*((byte *)(x))) +#define MEM_W(x) (*((word *)(x))) + +///04: 求最大值和最小值 +#define MAX(x,y) (((x)>(y)) ? (x) : (y)) +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) + +///05: 得到一个field在结构体(struct)中的偏移量 +#define FPOS(type,field) ((dword)&((type *)0)->field) + +///06: 得到一个结构体中field所占用的字节数 +#define FSIZ(type,field) sizeof(((type *)0)->field) + +///07: 按照LSB格式把两个字节转化为一个Word +#define FLIPW(ray) ((((word)(ray)[0]) * 256) + (ray)[1]) + +///08: 按照LSB格式把一个Word转化为两个字节 +#define FLOPW(ray,val) (ray)[0] = ((val)/256); (ray)[1] = ((val) & 0xFF) + +///09: 得到一个变量的地址(word宽度) +#define B_PTR(var) ((byte *) (void *) &(var)) +#define W_PTR(var) ((word *) (void *) &(var)) + +///10: 得到一个字的高位和低位字节 +#define WORD_LO(xxx) ((byte) ((word)(xxx) & 255)) +#define WORD_HI(xxx) ((byte) ((word)(xxx) >> 8)) + +///11: 返回一个比X大的最接近的8的倍数 +#define RND8(x) ((((x) + 7)/8) * 8) + +///12: 将一个字母转换为大写 +#define UPCASE(c) (((c)>='a' && (c) <= 'z') ? ((c) - 0x20) : (c)) +#define ToUpper(c) (c & ~0x20) + +///13: 判断字符是不是10进值的数字 +#define DECCHK(c) ((c)>='0' && (c)<='9') + +///14: 判断字符是不是16进值的数字 +#define HEXCHK(c) (((c) >= '0' && (c)<='9') ((c)>='A' && (c)<= 'F') \ +((c)>='a' && (c)<='f')) + +///15: 防止溢出的一个方法 +#define INC_SAT(val) (val=((val)+1>(val)) ? (val)+1 : (val)) + +///16: 返回数组元素的个数 +#define ARR_SIZE(a) (sizeof((a))/sizeof((a[0]))) + +///17: 返回一个无符号数n尾的值MOD_BY_POWER_OF_TWO(X,n)=X%(2^n) +#define MOD_BY_POWER_OF_TWO( val, mod_by ) ((dword)(val) & (dword)((mod_by)-1)) + +///18: 对于IO空间映射在存储空间的结构,输入输出处理 +#define inp(port) (*((volatile byte *)(port))) +#define inpw(port) (*((volatile word *)(port))) +#define inpdw(port) (*((volatile dword *)(port))) +#define outp(port,val) (*((volatile byte *)(port))=((byte)(val))) +#define outpw(port, val) (*((volatile word *)(port))=((word)(val))) +#define outpdw(port, val) (*((volatile dword *)(port))=((dword)(val))) + + + + + + +//#define DEBUG +//#define MMAP_INVALID_ARGUMENT /* invalid argument when mmap */ + + +/** + * Macros to help with debugging. Set SCULL_DEBUG to 1 enable + * debugging (which you can do from the Makefile); these macros work + * in both kernelspace and userspace. + */ + +/* undef it, just in case someone else defined it. */ + +#ifdef dbgprint +#undef dbgprint +#endif // dbgprint + +#ifdef dprint +#undef dprint +#endif // dprint + +#ifdef dout +#undef dount +#endif // dout + + +/**when you define DEBUG macro + dbgprint to use printk with line and funcitonname in kernel + dprint to use print without line and funcitonname in kernel + + + dbgprint to use printf with line and funcitonname in userspace + dprint to use printf without line and funcitonname in userspace + it's the same to dbgcout and dcout in userspace + +*/ +#ifdef DEBUG + #if defined(dbgprint) || defined(dprint) || defined(dprintk) + #error "dbgprint, dprint or dprintk has been defined already..." + #endif + + + #ifdef __KERNEL__ /* in kernel modules */ + + #if defined(__FILE__) && defined(__LINE__) + //printk with line and function name + #define dbgprint(format, args...) \ + printk(KERN_INFO "[%20s, %4d] : "format, __FILE__, __LINE__, ##args) + #endif // ifdef defined(__FILE__) && defined(__LINE__) + + //printk without line and function name + #define dprint(format,args...) printk(KERN_INFO format, ##args) + #define dprintk(format,args...) printk(KERN_INFO format, ##args) + + + #else // userspace + + #if defined(dbgprint) || defined(dprint) || defined(dprintf) + #error "dbgprint, dprint or dprintk has been defined already..." + #endif + ////////// + /// printf for C language + /// + /// dbgprint PRINT "[file, line], information + /// + /// dprint PRINT "information" + /// dprintf PRINT "information" + ////////// + + /* Debugging is on and we are in userspace. */ + #define dprint(format, args...) printf(format, ## args) + #define dprintf(format, args...) printf(format, ## args) + + #if defined(__FILE__) && defined(__LINE__) + //printf with line and function name + #define dbgprint(format, args...) \ + printf("[%20s,%4d] : "format, __FILE__, __LINE__, ##args) + #endif // ifdef defined(__FILE__) && defined(__LINE__) + + + ////////// + /// cout for C++ language + // + // dbgout PRINT "[file, line], information + // + // dcout PRINT "information" + // debug PRINT "information" + ////////// + #ifdef __cplusplus + + #if defined(dbgout) || defined(cout) || defined(debug) + #error "dbgprint, dprint or dprintk has been defined already..." + #endif + + #if defined(__FILE__) && defined(__LINE__) + #define dbgcout std::cout <<"[" <= 0; i--); \ + char *fname = malloc(strlen(fileName) - i); \ + strcpy(fname, fileName + i + 1); \ + printf("File: %s ", fname); \ + free(fname); \ + }while( 0 ); +# +# +#define __file__ __FILE__ +#define FILENAME() do \ + { int i = strlen(__FILE__) - 1; \ + for( ; \ + __FILE__[i] != '\\' && __FILE__[i] != '/'; \ + i--); \ + char *fname = malloc(strlen(__FILE__) - i); \ + strcpy(fname, __FILE__ + i + 1); \ + printf("FileName: %s", fname); \ + free(fname); \ + }while( 0 ); +# +# +#define __line__ __LINE__ /// +#define LINE( ) do \ + { \ + printf("Line: %d", __LINE__); \ + }while( 0 ); +# +# +#define __FUNC__ __func__ /// +#define FUNC( ) do \ + { \ + printf("Function: %s", __FUNC__); \ + }while( 0 ); +# +# +#define FILE_FUNC_LINE( ) do \ + { \ + FILENAME( ); \ + putchar(' '); \ + FUNC( ); \ + putchar(' '); \ + LINE( ); \ + putchar('\n'); \ + }while(0); + + + +#if !defined(offset) && !defined(container_of) + +#define offsetof(type, member) ((size_t) &((type *)0)->member) + +/* + * get the struct(type) from the pointer pstr(one of his member) + * ptr : the pointer point to the member whose type is member you know + * type : the type of the struct you want get + * member : the member's name in type struct + */ +#define container_of(ptr, type, member) \ +({ \ + const typeof( ((type *)0)->member) *m_ptr = (ptr); \ + (type *)( (char *)m_ptr - offsetof(type, member) ); \ +}) + +#endif + +/* +* safe sprintf +* It will not be out of range. +*/ +/* +#define safe_sprintf(start, n, p, format, args...); \ + { \ + if( (p - start) < n ) \ + { \ + snprintf( (char *)p, (n - (p - start)), format, ##args ); \ + } \ + } +*/ +#define safe_sprintf(start, n, p, format, args...) \ + (((p - start) < n ) && snprintf( (char *)p, (n - (p - start)), format, ##args )) + + + + +#endif /* _COMMON_H_ */ diff --git a/study/proc/proc_final/config.h b/study/proc/proc_final/config.h new file mode 100644 index 0000000..4a4e366 --- /dev/null +++ b/study/proc/proc_final/config.h @@ -0,0 +1,76 @@ +/* +* Author: HIT CS HDMC team. +* Last modified by zhaozhilong: 2010-1-14 +*/ +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +#define DEBUG + + +/* + * 3.10以后内核的proc文件 + * 废弃了原来的create_proc_entry接口 + * 3.9 http://lxr.free-electrons.com/ident?v=3.9&i=create_proc_entry + * 2.10 http://lxr.free-electrons.com/ident?v=3.10;i=create_proc_entry + * + * 而引入了 + * 1. proc_create创建proc文件, + * 2. seq_file(Sequence file:序列文件)接口 + * 3. signal_file接口 + * + * **proc_create创建proc文件** + * 使用proc_create需要关联file_operations + * 首先要调用创建proc文件的函数,需要绑定flie_operations + * + * ***seq_file接口操作proc文件* + * http://blog.chinaunix.net/uid-28253945-id-3382865.html + * 由于procfs的默认操作函数只使用一页的缓存, + * 在处理较大的proc文件时就有点麻烦, + * 并且在输出一系列结构体中的数据时也比较不灵活, + * 需要自己在read_proc函数中实现迭代,容易出现Bug。 + * 所以内核黑客们对一些/proc代码做了研究,抽象出共性, + * 最终形成了seq_file(Sequence file:序列文件)接口。 + * 这个接口提供了一套简单的函数来解决以上proc接口编程时存在的问题, + * 使得编程更加容易,降低了Bug出现的机会。 + * 在需要创建一个由一系列数据顺序组合而成的虚拟文件或一个较大的虚拟文件时, + * 推荐使用seq_file接口。 + * + * 一般地,内核通过在procfs文件系统下建立文件来向用户空间提供输出信息, + * 用户空间可以通过任何文本阅读应用查看该文件信息, + * 但是procfs 有一个缺陷,如果输出内容大于1个内存页,需要多次读, + * 因此处理起来很难,另外,如果输出太大,速度比较慢, + * 有时会出现一些意想不到的情况, + * Alexander Viro实现了一套新的功能,使得内核输出大文件信息更容易, + * 该功能出现在2.4.15(包括2.4.15)以后的所有2.4内核以及2.6内核中, + * 尤其 是在2.6内核中,已经大量地使用了该功能。 + * 要想使用seq_file功能,开发者需要包含头文件linux/seq_file.h, + * 并定义与设置一个seq_operations结构(类似于file_operations结构): + * + * 但是我个人认为,并不是只有procfs才可以使用这个seq_file接口, + * 因为其实seq_file是实现的是一个操作函数集,这个函数集并不是与proc绑定的, + * 同样可以用在其他的地方。 + * + **/ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) + + #define CREATE_PROC_ENTRY +// #warning "use create_proc_entry in " #LINUX_VERSION_CODE + +#else + #define PROC_CREATE +// #warning "use proc_create in " #LINUX_VERSION_CODE + #define PROC_SEQ_FILE_OPERATIONS + #include + #include +#endif + +#if defined(CREATE_PROC_ENTRY) || defined(PROC_CREATE) + +#else + #error "you must define one of CREATE_PROC_ENTRY and PROC_CREATE" +#endif + + + +#endif /* _CONFIG_H_ */ diff --git a/study/proc/proc_final/main.c b/study/proc/proc_final/main.c new file mode 100644 index 0000000..cf202fe --- /dev/null +++ b/study/proc/proc_final/main.c @@ -0,0 +1,237 @@ +/* +* Author: HIT CS HDMC team. +* Create: 2010-3-12 8:50 +* Last modified: 2010-6-13 14:06:20 +* Description: +* Memory fault injection engine running as a kernel module. +* This module will create "/proc/memoryEngine/" directory and 9 proc nodes. +* Write paramenters and request to these proc nodes and read the output from related proc node. +*/ + +#include "main.h" + + + +/* +* proc entries +*/ +struct proc_dir_entry *dir = NULL; // the directory of the Moudle +struct proc_dir_entry *proc_write_only = NULL; // write only +struct proc_dir_entry *proc_read_only = NULL; // read only +struct proc_dir_entry *proc_read_write = NULL; // rw + +unsigned long write_only; +unsigned long read_only; +unsigned long read_write; + + + +EXPORT_SYMBOL(write_only); +EXPORT_SYMBOL(read_only); +EXPORT_SYMBOL(read_write); + + + + + +extern const struct file_operations proc_read_only_fops; /* RW */ +extern const struct file_operations proc_read_write_fops; /* RW */ +extern const struct file_operations proc_write_only_fops; /* WO */ + +static int __init proc_test_init(void) +{ + /* + * create a direntory named "memoryEngine" in /proc for the moudles + * as the interface between the kernel and the user program. + * + */ + dir = proc_mkdir("proc_test", NULL); + if(dir == NULL) + { + dbginfo("Can't create "PROC_DIR"\n"); + return FAIL; + } + dbginfo("PROC_MKDIR "); + printk("Create /proc/memoryEngine success...\n"); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) + /// modify by gatieme for system porting NeoKylin-linux-3.14/16 + /// error: dereferencing pointer to incomplete type + dir->owner = THIS_MODULE; +#endif + + + /// modify by gatieme for system porting NeoKylin-linux-3.14/16 @ 2016--03-28 20:08 + /* + * == + * write in STACK_OVER_FLOW http://stackoverflow.com/questions/26808325/implicit-declaration-of-function-create-proc-entry + * == + * + * proc filesystem has been refactored in 3.10, + * the function `create_proc_entry` has been removed, + * you should use the full featured `proc_create function` family. + * + * Note that the signatures are different, you can find them in LXR + * 3.10 version: http://lxr.free-electrons.com/source/include/linux/proc_fs.h?v=3.10 + * 3.9 version: http://lxr.free-electrons.com/source/include/linux/proc_fs.h?v=3.9 + * + * You can find greater explanation of using full featured /proc functions in the book Linux Device Drivers 4, + * or, if you want shorter solution, check this link (https://github.com/jesstess/ldd4/blob/master/scull/main.c) + * where you can see how the struct file_operations has been used. You do not have to setup to all fields of the struct. + * + * but the function remove_proc_remove, you can do nothing for it, becase there are tow function for it + * static inline void proc_remove(struct proc_dir_entry *de) {} + * #define remove_proc_entry(name, parent) do {} while (0) + */ + + + //////////////////////////////////////////////////////////////////////////// + /// create a file named "read only" in direntory + //////////////////////////////////////////////////////////////////////////// +#ifdef CREATE_PROC_ENTRY + + proc_read_only = create_proc_entry("ctl", PERMISSION, dir); + if(proc_read_only == NULL) + { + dbginfo("Can't create "PROC_DIR PROC_READ_ONLY_ENTRY "\n"); + ret = FAIL; + + goto create_read_only_failed; + + } + + proc_read_only->write_proc = proc_read_only; // write only + + //proc_read_only->owner = THIS_MODULE; + + dbginfo("CREATE_PROC_ENTRY "); +#elif defined PROC_CREATE + + proc_read_only = proc_create("ctl", PERMISSION, dir, &proc_read_only_fops); + + if(proc_read_only == NULL) + { + dbginfo("Can't create "PROC_DIR PROC_READ_ONLY_ENTRY "\n"); + ret = FAIL; + + goto create_read_only_failed; + } + dbginfo("PROC_CREATE "); +#endif + printk("Create "PROC_DIR PROC_READ_ONLY_ENTRY " success...\n"); + + //////////////////////////////////////////////////////////////////////////// + /// create a file named "write only" in direntory + //////////////////////////////////////////////////////////////////////////// +#ifdef CREATE_PROC_ENTRY + + proc_write_only = create_proc_entry(PROC_DIR, PERMISSION, dir); + + if(proc_write_only == NULL) + { + dbginfo("Can't create " PROC_DIR PROC_WRITE_ONLY_ENTRY"\n"); + ret = FAIL; + + goto create_write_only_failed; + } + proc_write_only->write_proc = proc_write_pid; /// write only + //proc_write_only->owner = THIS_MODULE; + + dbginfo("CREATE_PROC_ENTRY "); + +#elif defined PROC_CREATE + + proc_write_only = proc_create("pid", PERMISSION, dir, &proc_write_only_fops); + + if(proc_write_only == NULL) + { + dbginfo("Can't create " PRPC_DIR PROC_WRITE_ONLY_ENTRY "\n"); + ret = FAIL; + + goto create_write_only_failed; + } + dbginfo("PROC_CREATE "); +#endif + printk("Create " PRPC_DIR PROC_WRITE_ONLY_ENTRY " success...\n"); + + + + + //////////////////////////////////////////////////////////////////////////// + /// create a file named "read_write" in direntory + //////////////////////////////////////////////////////////////////////////// +#ifdef CREATE_PROC_ENTRY + + proc_read_write = create_proc_entry("virtualAddr", PERMISSION, dir); + if(proc_read_write == NULL) + { + dbginfo("Can't create " PRPC_DIR PROC_READ_WRITE_ENTRY "\n"); + ret = FAIL; + + goto create_read_write_failed; + } + proc_read_write->read_proc = proc_read_va; // can read + proc_read_write->write_proc = proc_write_va; // can write + //proc_read_write->owner = THIS_MODULE; + + dbginfo("CREATE_PROC_ENTRY "); +#elif defined PROC_CREATE + + proc_read_write = proc_create("virtualAddr", PERMISSION, dir, &proc_read_write_fops); + + if(proc_read_write == NULL) + { + dbginfo("Can't create " PRPC_DIR PROC_READ_WRITE_ENTRY "\n"); + ret = FAIL; + + goto create_va_failed; + } + dbginfo("PROC_CREATE "); +#endif + + printk("Create " PRPC_DIR PROC_READ_WRITE_ENTRY " success...\n"); + + dbginfo("Memory engine module init\n"); + + return OK; + + + +create_read_write_failed : + remove_proc_entry(PROC_WRITE_ONLY_ENTRY, dir); + +create_write_only_failed : + remove_proc_entry(PROC_READ_ONLY_ENTRY, dir); + +create_read_only_failed : + remove_proc_entry(PROC_DIR, NULL); + + return ret; +} + + + +/* +* uninit memory fault injection module +*/ +static void __exit exitME(void) +{ + remove_proc_entry("read_write", dir); + printk("Remove /proc/proc_test/read_write success\n"); + + remove_proc_entry("write_only", dir); + printk("Remove /proc/proc_test/write_only success\n"); + + remove_proc_entry("read_only", dir); + printk("Remove /proc/proc_test/read_only success\n"); + + dbginfo("Memory proc_test module exit\n"); +} + +module_init(initPROC); +module_exit(exitPROC); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Gatieme @ HIT CS HDMC team"); +MODULE_DESCRIPTION("Memory Engine Module."); + diff --git a/study/proc/proc_final/main.h b/study/proc/proc_final/main.h new file mode 100644 index 0000000..a130a39 --- /dev/null +++ b/study/proc/proc_final/main.h @@ -0,0 +1,34 @@ +/* +* Author: HIT CS HDMC team. +* Create: 2010-3-12 8:20:01 +* Last modified: 2010-6-13 14:13:47 +*/ + +#ifndef __MAIN_H_INCLUDE__ +#define __MAIN_H_INCLUDE__ + +/* +* common include header files +*/ + +#include "common.h" + + +#define MAX_LINE 256 /// max length of a line +#define DELIMITER '\n' /// the char is used to split the taskinfo +#define PERMISSION 0644 /// proc node permission +/* +* return values +*/ +#define OK 0 +#define FAIL -1 + +/* + * proc files + */ +#define PROC_DIR "/proc/proc_test" +#define PROC_READ_ONLY_ENTRY "read_only" +#define PROC_WRITE_ONLY_ENTRY "write_only" +#define PROC_READ_WRITE_ENTRY "read_write" + +#endif // #define __MAIN_H_INCLUDE__ diff --git a/study/proc/proc_final/ro.c b/study/proc/proc_final/ro.c new file mode 100644 index 0000000..e29acfb --- /dev/null +++ b/study/proc/proc_final/ro.c @@ -0,0 +1,75 @@ +/* +* Author: HIT CS HDMC team. +* Create: 2010-3-12 8:50 +* Last modified: 2010-6-13 14:06:20 +* Description: +* Memory fault injection engine running as a kernel module. +* This module will create "/proc/memoryEngine/" directory and 9 proc nodes. +* Write roramenters and request to these proc nodes and read the output from related proc node. +*/ + +#include "common.h" + + + + + + +char ro_buffer[MAX_LINE] = "READ ONLY!!!"; + + +#ifndef PROC_SEQ_FILE_OPERATIONS + +/* +* +*/ +int proc_read_ro(char * page,char **start, off_t off, int count, int * eof,void * data) +{ + int iLen; + iLen = sprintf(page, "%s", ro_buffer); + return iLen; +} + +const struct file_operations ro_fops = +{ + .owner = THIS_MODULE, + .read = proc_read_ro, // read only + //.write = proc_write_ro, // write only +}; + +#else + +// seq_operations -> show +static int seq_show_ro(struct seq_file *m, void *v) +{ + /* + char buf[MAX_LINE]; + int ret = 0; + + ret = sprintf(buf, "%ls", ack_ro); + */ + + seq_printf(m, "%s", ro_buffer); + + return 0; //!! must be 0, or will show nothing T.T +} + + +// seq_operations -> open +static int proc_open_ro(struct inode *inode, struct file *file) +{ + return single_open(file, seq_show_ro, NULL); +} + +const struct file_operations proc_ro_fops = +{ + .owner = THIS_MODULE, + .open = proc_open_ro, + .read = seq_read, + //.write = proc_write_ro, + .llseek = seq_lseek, + .release = single_release, + +}; + +#endif diff --git a/study/proc/proc_final/rw.c b/study/proc/proc_final/rw.c new file mode 100644 index 0000000..4e2b37d --- /dev/null +++ b/study/proc/proc_final/rw.c @@ -0,0 +1,87 @@ +/* +* Author: HIT CS HDMC team. +* Create: 2010-3-12 8:50 +* Last modified: 2010-6-13 14:06:20 +* Description: +* Memory fault injection engine running as a kernel module. +* This module will create "/proc/memoryEngine/" directory and 9 proc nodes. +* Write rwramenters and request to these proc nodes and read the output from related proc node. +*/ + +#include "main.h" + + + +/* +* +*/ +int proc_write_rw(struct file *file, const char *buffer, unsigned long count, void * data) +{ + int iRet; + char srw[MAX_LINE]; + + if(count <= 0) { return FAIL; } + memset(srw, '\0', sizeof(srw)); + iRet = copy_from_user(srw, buffer, count); + if(iRet) { return FAIL; } + iRet = sscanf(srw,"%lx",&rw); + if(iRet != 1) { return FAIL; } + dbginfo("Rcv rw:0x%lx\n",rw); + return count; +} + +#ifndef PROC_SEQ_FILE_OPERATIONS +/* +* +*/ +int proc_read_rw(char * rwge,char **start, off_t off, int count, int * eof,void * data) +{ + int iLen; + dbginfo("0x%lx\n", ack_rw); + iLen = sprintf(rwge, "%lx", ack_rw); + return iLen; +} + +const struct file_operations proc_rw_fops = +{ + .owner = THIS_MODULE, + .read = proc_read_rw, // read + .write = proc_write_rw, // write +}; + +#else + +// seq_operations -> show +static int seq_show_rw(struct seq_file *m, void *v) +{ + /* + char buf[MAX_LINE]; + int ret = 0; + dbginfo("0x%lx\n", ack_rw); + ret = sprintf(buf, "%lx", ack_rw); + */ + + dbginfo("0x%lx\n", ack_rw); + seq_printf(m, "%lx", ack_rw); + + return 0; //!! must be 0, or will show nothing T.T +} + + +// seq_operations -> open +static int proc_open_rw(struct inode *inode, struct file *file) +{ + return single_open(file, seq_show_rw, NULL); +} + +const struct file_operations proc_rw_fops = +{ + .owner = THIS_MODULE, + .open = proc_open_rw, + .read = seq_read, + .write = proc_write_rw, + .llseek = seq_lseek, + .release = single_release, +}; + +#endif diff --git a/study/proc/proc_final/wo.c b/study/proc/proc_final/wo.c new file mode 100644 index 0000000..fcf3782 --- /dev/null +++ b/study/proc/proc_final/wo.c @@ -0,0 +1,60 @@ +/* +* Author: HIT CS HDMC team. +* Create: 2010-3-12 8:50 +* Last modified: 2010-6-13 14:06:20 +* Description: +* Memory fault injection engine running as a kernel module. +* This module will create "/proc/memoryEngine/" directory and 9 proc nodes. +* Write paramenters and request to these proc nodes and read the output from related proc node. +*/ + +#include "main.h" + +/* +* proc entries +*/ + + + +char ro_buffer[MAX_LINE] = +/* +* +*/ +int proc_write_ctl( struct file *file, + const char *buffer, + unsigned long count, + void * data) +{ + int iRet; + char sCtl[MAX_LINE]; + + if(count <= 0) + { + return FAIL; + } + + memset(sCtl, '\0', sizeof(sCtl)); + + iRet = copy_from_user(sCtl, buffer, count); + if(iRet) + { + return FAIL; + } + + iRet = sscanf(sCtl,"%d",&ctl); + if(iRet != 1) + { + return FAIL; + } + dbginfo("Rcv ctl : %d\n", ctl); + do_request( ); + + return count; +} + +const struct file_operations proc_ctl_fops = +{ + .owner = THIS_MODULE, + //.read = proc_read_ctl, // can read + .write = proc_write_ctl, // write only +}; diff --git a/study/proc/seq_file_exam/seq_file_exam.c b/study/proc/seq_file_exam/seq_file_exam.c index 7ac3ae5..81dda57 100644 --- a/study/proc/seq_file_exam/seq_file_exam.c +++ b/study/proc/seq_file_exam/seq_file_exam.c @@ -72,7 +72,7 @@ static struct file_operations exam_seq_fops = { static int __init exam_seq_init(void) { - entry = create_proc_entry("exam_esq_file", 0, NULL); + entry = create_proc_entry("exam_esq_file", 0666, NULL); if (entry) entry->proc_fops = &exam_seq_fops;