From e92d98c6d0f025a7b8203997fd9ebca91a4f3adf Mon Sep 17 00:00:00 2001 From: ioacademy-jikim Date: Wed, 19 Aug 2015 19:26:23 +0900 Subject: [PATCH] first sample --- 01_day/Makefile | 10 ++ 01_day/for_each_process.c | 21 +++ 01_day/jni/Android.mk | 8 ++ 01_day/jni/myapp.c | 9 ++ 01_day/macro.c | 155 +++++++++++++++++++++ 01_day/misc_dev.c | 44 ++++++ 01_day/module1.c | 15 ++ 01_day/module2.c | 16 +++ 01_day/module3.c | 18 +++ 01_day/my_dev.c | 36 +++++ 01_day/my_process.c | 19 +++ 01_day/my_process_list.c | 31 +++++ 02_day/.gen_dev.c.swp | Bin 0 -> 12288 bytes 02_day/Makefile | 10 ++ 02_day/bit.c | 77 +++++++++++ 02_day/gen_dev.c | 45 ++++++ 02_day/ioctl_dev.c | 58 ++++++++ 02_day/jni/Android.mk | 8 ++ 02_day/jni/myapp.c | 10 ++ 02_day/jni/rdwr_app.c | 57 ++++++++ 02_day/list.c | 67 +++++++++ 02_day/macro.c | 12 ++ 02_day/misc_dev.c | 44 ++++++ 02_day/mknod.c | 10 ++ 02_day/my_timer.c | 65 +++++++++ 02_day/rdwr_dev.c | 128 +++++++++++++++++ 03_day/.kernel_file.c.swp | Bin 0 -> 12288 bytes 03_day/.mmap_dev.c.swp | Bin 0 -> 12288 bytes 03_day/.my_memory.c.swp | Bin 0 -> 12288 bytes 03_day/Makefile | 10 ++ 03_day/blocking_dev.c | 75 ++++++++++ 03_day/ioctl_dev.c | 99 ++++++++++++++ 03_day/jni/Android.mk | 8 ++ 03_day/jni/ioctl_app.c | 52 +++++++ 03_day/jni/mmap_app.c | 21 +++ 03_day/jni/myapp.c | 10 ++ 03_day/jni/poll_app.c | 59 ++++++++ 03_day/jni/rdwr_app.c | 57 ++++++++ 03_day/kernel_file.c | 29 ++++ 03_day/mmap.c | 34 +++++ 03_day/mmap_dev.c | 60 ++++++++ 03_day/my_int.c | 28 ++++ 03_day/my_memory.c | 56 ++++++++ 03_day/poll_1.c | 74 ++++++++++ 03_day/poll_dev.c | 87 ++++++++++++ 03_day/type.c | 10 ++ 04_day/.input_dev.c.swp | Bin 0 -> 12288 bytes 04_day/Makefile | 10 ++ 04_day/flex.c | 34 +++++ 04_day/input_dev.c | 52 +++++++ 04_day/jni/Android.mk | 8 ++ 04_day/jni/input_app.c | 23 ++++ 04_day/jni/queue_app.c | 21 +++ 04_day/my_work.c | 37 +++++ 04_day/queue.c | 48 +++++++ 04_day/queue_dev.c | 120 ++++++++++++++++ 05_day/Makefile | 10 ++ 05_day/jni/Android.mk | 8 ++ 05_day/jni/input_app.c | 23 ++++ 05_day/jni/queue_app.c | 21 +++ 05_day/kobject-example.c | 137 +++++++++++++++++++ 05_day/kset-example.c | 279 ++++++++++++++++++++++++++++++++++++++ 62 files changed, 2573 insertions(+) create mode 100644 01_day/Makefile create mode 100644 01_day/for_each_process.c create mode 100644 01_day/jni/Android.mk create mode 100644 01_day/jni/myapp.c create mode 100644 01_day/macro.c create mode 100644 01_day/misc_dev.c create mode 100644 01_day/module1.c create mode 100644 01_day/module2.c create mode 100644 01_day/module3.c create mode 100644 01_day/my_dev.c create mode 100644 01_day/my_process.c create mode 100644 01_day/my_process_list.c create mode 100644 02_day/.gen_dev.c.swp create mode 100644 02_day/Makefile create mode 100644 02_day/bit.c create mode 100644 02_day/gen_dev.c create mode 100644 02_day/ioctl_dev.c create mode 100644 02_day/jni/Android.mk create mode 100644 02_day/jni/myapp.c create mode 100644 02_day/jni/rdwr_app.c create mode 100644 02_day/list.c create mode 100644 02_day/macro.c create mode 100644 02_day/misc_dev.c create mode 100644 02_day/mknod.c create mode 100644 02_day/my_timer.c create mode 100644 02_day/rdwr_dev.c create mode 100644 03_day/.kernel_file.c.swp create mode 100644 03_day/.mmap_dev.c.swp create mode 100644 03_day/.my_memory.c.swp create mode 100644 03_day/Makefile create mode 100644 03_day/blocking_dev.c create mode 100644 03_day/ioctl_dev.c create mode 100644 03_day/jni/Android.mk create mode 100644 03_day/jni/ioctl_app.c create mode 100644 03_day/jni/mmap_app.c create mode 100644 03_day/jni/myapp.c create mode 100644 03_day/jni/poll_app.c create mode 100644 03_day/jni/rdwr_app.c create mode 100644 03_day/kernel_file.c create mode 100644 03_day/mmap.c create mode 100644 03_day/mmap_dev.c create mode 100644 03_day/my_int.c create mode 100644 03_day/my_memory.c create mode 100644 03_day/poll_1.c create mode 100644 03_day/poll_dev.c create mode 100644 03_day/type.c create mode 100644 04_day/.input_dev.c.swp create mode 100644 04_day/Makefile create mode 100644 04_day/flex.c create mode 100644 04_day/input_dev.c create mode 100644 04_day/jni/Android.mk create mode 100644 04_day/jni/input_app.c create mode 100644 04_day/jni/queue_app.c create mode 100644 04_day/my_work.c create mode 100644 04_day/queue.c create mode 100644 04_day/queue_dev.c create mode 100644 05_day/Makefile create mode 100644 05_day/jni/Android.mk create mode 100644 05_day/jni/input_app.c create mode 100644 05_day/jni/queue_app.c create mode 100644 05_day/kobject-example.c create mode 100644 05_day/kset-example.c diff --git a/01_day/Makefile b/01_day/Makefile new file mode 100644 index 0000000..5a2ef40 --- /dev/null +++ b/01_day/Makefile @@ -0,0 +1,10 @@ +obj-m = misc_dev.o + +KDIR = /usr/src/tegra +PWD = $(shell pwd) + +default: + make -C $(KDIR) SUBDIRS=$(PWD) modules + +clean: + make -C $(KDIR) SUBDIRS=$(PWD) clean diff --git a/01_day/for_each_process.c b/01_day/for_each_process.c new file mode 100644 index 0000000..b3f5f51 --- /dev/null +++ b/01_day/for_each_process.c @@ -0,0 +1,21 @@ +#include // my_init +#include // printk +#include // task_struct + +int my_init(void) +{ + struct task_struct *p; + for_each_process(p) + printk("pid=%d , comm=%s\n", p->pid, p->comm); + + return 0; +} + +void my_exit(void) +{ +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/01_day/jni/Android.mk b/01_day/jni/Android.mk new file mode 100644 index 0000000..a6207b2 --- /dev/null +++ b/01_day/jni/Android.mk @@ -0,0 +1,8 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_CFLAGS := -fPIE +LOCAL_LDFLAGS := -fPIE -pie +LOCAL_MODULE := myapp +LOCAL_SRC_FILES := myapp.c +include $(BUILD_EXECUTABLE) + diff --git a/01_day/jni/myapp.c b/01_day/jni/myapp.c new file mode 100644 index 0000000..6b7f4b8 --- /dev/null +++ b/01_day/jni/myapp.c @@ -0,0 +1,9 @@ +#include +int main() +{ + int fd; + fd = open( "/dev/mydev", O_RDONLY ); + close(fd); + return 0; +} + diff --git a/01_day/macro.c b/01_day/macro.c new file mode 100644 index 0000000..6290ab6 --- /dev/null +++ b/01_day/macro.c @@ -0,0 +1,155 @@ +#if 1 +#include + +#ifdef MODULE +#define module_init( fn ) \ + int init_module(void) __attribute__((alias(#fn))) +#else +#define module_init( fn ) __initcall(x); +#endif + +int my_init(void) +{ + printf("init_module()\n"); + return 0; +} + +module_init( my_init ); + +int main() +{ + init_module(); + return 0; +} +#endif +#if 0 +#include + +void bar(void) +{ + printf("bar()\n"); +} + +void foo(void) __attribute__((alias("bar"))); + +int main() +{ + foo(); + return 0; +} +#endif +#if 0 +#include + +#define ___PASTE(a,b) a##b +#define __PASTE(a,b) ___PASTE(a,b) +#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) + +#define __MODULE_LICENSE( license, info ) \ + static const char __UNIQUE_ID(license)[] = "license" "=" info + + +__MODULE_LICENSE(license, "GPL"); __MODULE_LICENSE(license, "BSD"); + +int main() +{ + return 0; +} +#endif +#if 0 +#include + +#define __FOO(a,b) a##b +#define FOO( a,b ) __FOO(a,b) +#define __MODULE_LICENSE( license, info ) \ + static const char FOO(license,__LINE__)[] = "license" "=" info + + +__MODULE_LICENSE(license, "GPL"); __MODULE_LICENSE(license, "BSD"); + +int main() +{ + return 0; +} +#endif +#if 0 +#include + +#define BAR hello + +int main() +{ + //printf("%s\n", "license" "=" "GPL" ); + printf("%s\n", "license=GPL" ); + return 0; +} +#endif +#if 0 +#include + +#define __FOO(x) #x +#define FOO(x) __FOO(x) +#define BAR hello + +int main() +{ + printf("%s\n", FOO(BAR) ); + return 0; +} +#endif +#if 0 +#include + +#define FOO(x) #x +#define BAR hello + +int main() +{ + printf("%s\n", FOO(BAR) ); + return 0; +} +#endif +#if 0 +#include + +//#define __stringify_1(x...) #x +//#define __stringify(x...) __stringify_1(x) + +#define __stringify(x...) #x +int main() +{ + printf("%s\n", __stringify(license)); + return 0; +} +#endif +#if 0 +#include + +# define __used __attribute__((__used__)) +int main() +{ + int __used __attribute__((unused)) glob; + + //printf("glob=%d\n", glob ); + return 0; +} +#endif + +#if 0 +static const char a[] +__attribute__((section(".modinfo"))) += "hello"; + +int main() +{ + return 0; +} +#endif +#if 0 +static const char a[] = "hello"; + +int main() +{ + return 0; +} +#endif diff --git a/01_day/misc_dev.c b/01_day/misc_dev.c new file mode 100644 index 0000000..cb90e95 --- /dev/null +++ b/01_day/misc_dev.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include //misc_register + +int my_open (struct inode *inode, struct file *filp) +{ + printk("my_open()\n"); + return 0; +} +int my_close(struct inode *inode, struct file *filp) +{ + printk("my_close()\n"); + return 0; +} + +static struct file_operations fops = +{ + .open = my_open, + .release = my_close, +}; + +static struct miscdevice misc = +{ + .minor = MISC_DYNAMIC_MINOR, + .name = "mydev", + .fops = &fops, +}; + +int my_init(void) +{ + misc_register( &misc ); + return 0; +} + +void my_exit(void) +{ + misc_deregister( &misc ); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/01_day/module1.c b/01_day/module1.c new file mode 100644 index 0000000..be8b477 --- /dev/null +++ b/01_day/module1.c @@ -0,0 +1,15 @@ +#include +#include + +int init_module(void) +{ + printk("init_module()\n"); + return 0; +} + +void cleanup_module(void) +{ + printk("cleanup_module()\n"); +} + + diff --git a/01_day/module2.c b/01_day/module2.c new file mode 100644 index 0000000..b0c4ed4 --- /dev/null +++ b/01_day/module2.c @@ -0,0 +1,16 @@ +#include +#include + +int init_module(void) +{ + printk("init_module()\n"); + return 0; +} + +void cleanup_module(void) +{ + printk("cleanup_module()\n"); +} + +MODULE_LICENSE("GPL"); + diff --git a/01_day/module3.c b/01_day/module3.c new file mode 100644 index 0000000..95c1601 --- /dev/null +++ b/01_day/module3.c @@ -0,0 +1,18 @@ +#include +#include + +int my_init(void) +{ + printk("init_module()\n"); + return 0; +} + +void my_exit(void) +{ + printk("cleanup_module()\n"); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/01_day/my_dev.c b/01_day/my_dev.c new file mode 100644 index 0000000..56993b1 --- /dev/null +++ b/01_day/my_dev.c @@ -0,0 +1,36 @@ +#include +#include +#include + +int my_open (struct inode *inode, struct file *filp) +{ + printk("my_open()\n"); + return 0; +} +int my_close(struct inode *inode, struct file *filp) +{ + printk("my_close()\n"); + return 0; +} + +static struct file_operations fops = +{ + .open = my_open, + .release = my_close, +}; + +int my_init(void) +{ + register_chrdev(200, "mydev", &fops ); + return 0; +} + +void my_exit(void) +{ + unregister_chrdev( 200, "mydev" ); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/01_day/my_process.c b/01_day/my_process.c new file mode 100644 index 0000000..97bc1da --- /dev/null +++ b/01_day/my_process.c @@ -0,0 +1,19 @@ +#include // my_init +#include // printk +#include // task_struct + +int my_init(void) +{ + struct task_struct *p = current; + printk("pid=%d, comm=%s\n", p->pid, p->comm ); + return 0; +} + +void my_exit(void) +{ +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/01_day/my_process_list.c b/01_day/my_process_list.c new file mode 100644 index 0000000..9d7fb93 --- /dev/null +++ b/01_day/my_process_list.c @@ -0,0 +1,31 @@ +#include // my_init +#include // printk +#include // task_struct +#include // kernel list + +int my_init(void) +{ + struct task_struct *p; + struct list_head *temp; + + for( temp = current->tasks.next; + temp!= ¤t->tasks; + temp = temp->next ) + { + p = list_entry( temp, struct task_struct, tasks ); + printk("pid=%d , comm=%s\n", p->pid, p->comm); + } + p = list_entry( temp, struct task_struct, tasks ); + printk("pid=%d , comm=%s\n", p->pid, p->comm); + + return 0; +} + +void my_exit(void) +{ +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/02_day/.gen_dev.c.swp b/02_day/.gen_dev.c.swp new file mode 100644 index 0000000000000000000000000000000000000000..de66c2faba52c8b5f7797a65686b5384e2752414 GIT binary patch literal 12288 zcmeI2O=}ZD7{{mHf>x!Typ1WXo48H4@fB(XwLz57b#<-cZOE$YM!;32pV)z{t zMVQ@T89%Hlh1Zakmhq~CTsDBgOcF`47$_}d#b1(mQQ6@|&vSXUxr&>t$(zAN;EOGf zyBq@=6V}*r9Mn23I_4&4%SxdW8FBA-4qu9@78@P79HmSamk-zDmO|YjmEEXrif?YO zySwx$+hk`^e1f-Eo0ht9d1|)OR`W+*Qx$WkuTGZc9h=m%O9>)vR$}e8SE6)P2R?_p z#MkZQJl`od&eCDzt7y9xqa2MFqzFY-2^6uDVf6ExGMFoPW*D27|~C6EtwvzDGX_UHD8Dmd{|9!d@foFNzuY E1;WZq-~a#s literal 0 HcmV?d00001 diff --git a/02_day/Makefile b/02_day/Makefile new file mode 100644 index 0000000..f58c40a --- /dev/null +++ b/02_day/Makefile @@ -0,0 +1,10 @@ +obj-m = my_timer.o + +KDIR = /usr/src/tegra +PWD = $(shell pwd) + +default: + make -C $(KDIR) SUBDIRS=$(PWD) modules + +clean: + make -C $(KDIR) SUBDIRS=$(PWD) clean diff --git a/02_day/bit.c b/02_day/bit.c new file mode 100644 index 0000000..a0e9053 --- /dev/null +++ b/02_day/bit.c @@ -0,0 +1,77 @@ +#include +#define BITS_PER_LONG 64 +#define ffz(x) __ffs(~(x)) +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) +static __always_inline unsigned long __ffs(unsigned long word) +{ + int num = 0; + +#if BITS_PER_LONG == 64 + if ((word & 0xffffffff) == 0) { + num += 32; + word >>= 32; + } +#endif + if ((word & 0xffff) == 0) { + num += 16; + word >>= 16; + } + if ((word & 0xff) == 0) { + num += 8; + word >>= 8; + } + if ((word & 0xf) == 0) { + num += 4; + word >>= 4; + } + if ((word & 0x3) == 0) { + num += 2; + word >>= 2; + } + if ((word & 0x1) == 0) + num += 1; + return num; +} +static inline void set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + unsigned long flags; + + *p |= mask; +} + +unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) +{ + const unsigned long *p = addr; + unsigned long result = 0; + unsigned long tmp; + + while (size & ~(BITS_PER_LONG-1)) { + if (~(tmp = *(p++))) + goto found; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + if (!size) + return result; + + tmp = (*p) | (~0UL << size); + if (tmp == ~0UL) /* Are any bits zero? */ + return result + size; /* Nope. */ +found: + return result + ffz(tmp); +} + +int main() +{ + unsigned long a[1] = {0x0UL}; + unsigned long index; + index = find_first_zero_bit(a, 64); + printf("%lu\n", 64-index-1 ); + set_bit( 0, a ); + index = find_first_zero_bit(a, 64); + printf("%lu\n", 64-index-1 ); + return 0; +} diff --git a/02_day/gen_dev.c b/02_day/gen_dev.c new file mode 100644 index 0000000..4208945 --- /dev/null +++ b/02_day/gen_dev.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include + +int my_open (struct inode *inode, struct file *filp) +{ + printk("my_open()\n"); + return 0; +} +int my_close(struct inode *inode, struct file *filp) +{ + printk("my_close()\n"); + return 0; +} + +static struct file_operations fops = +{ + .open = my_open, + .release = my_close, +}; + +static dev_t devt; +static struct class *my_class; +int my_init(void) +{ + devt = MKDEV(200, 0); + my_class = class_create(THIS_MODULE, "mydev"); + register_chrdev(200, "mydev", &fops ); + device_create(my_class, 0, devt, &fops, "%s", "mydev"); + return 0; +} + +void my_exit(void) +{ + device_destroy(my_class, devt); + unregister_chrdev( 200, "mydev" ); + class_destroy(my_class); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/02_day/ioctl_dev.c b/02_day/ioctl_dev.c new file mode 100644 index 0000000..870bca0 --- /dev/null +++ b/02_day/ioctl_dev.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include //misc_register + +int my_open (struct inode *inode, struct file *filp) +{ + printk("my_open()\n"); + return 0; +} +int my_close(struct inode *inode, struct file *filp) +{ + printk("my_close()\n"); + return 0; +} + +long my_ioctl (struct file *filp, unsigned int cmd, unsigned long opt) +{ + _IOC_SIZE(cmd) + printk("my_ioctl()\n"); + switch( cmd ) + { + case 1: printk("LED_ON"); break; + case 2: printk("LED_OFF"); break; + } + return 0; +} + +static struct file_operations fops = +{ + .open = my_open, + .release = my_close, + .unlocked_ioctl = my_ioctl, + .compat_ioctl = my_ioctl, +}; + +static struct miscdevice misc = +{ + .minor = MISC_DYNAMIC_MINOR, + .name = "mydev", + .fops = &fops, +}; + +int my_init(void) +{ + misc_register( &misc ); + return 0; +} + +void my_exit(void) +{ + misc_deregister( &misc ); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/02_day/jni/Android.mk b/02_day/jni/Android.mk new file mode 100644 index 0000000..c4bf1ed --- /dev/null +++ b/02_day/jni/Android.mk @@ -0,0 +1,8 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_CFLAGS := -fPIE +LOCAL_LDFLAGS := -fPIE -pie +LOCAL_MODULE := myapp +LOCAL_SRC_FILES := rdwr_app.c +include $(BUILD_EXECUTABLE) + diff --git a/02_day/jni/myapp.c b/02_day/jni/myapp.c new file mode 100644 index 0000000..d8c9bfb --- /dev/null +++ b/02_day/jni/myapp.c @@ -0,0 +1,10 @@ +#include +int main() +{ + int fd; + fd = open( "/sys/devices/virtual/misc/mydev/uevent", O_WRONLY ); + write( fd, "add\n", 4 ); + close(fd); + return 0; +} + diff --git a/02_day/jni/rdwr_app.c b/02_day/jni/rdwr_app.c new file mode 100644 index 0000000..0075ca7 --- /dev/null +++ b/02_day/jni/rdwr_app.c @@ -0,0 +1,57 @@ +#include +#include +#include +int main() +{ + int fd, ret; + char buff[10]; + fd = open( "/dev/mydev", O_RDONLY ); + ret = read( fd, buff, sizeof buff ); + buff[ret] = 0; + printf( "buff[%s], ret=%d\n", buff, ret ); + close(fd); + return 0; +} +/* +#include +#include +#include +int main() +{ + int fd, ret; + int temp; + fd = open( "/dev/mydev", O_RDONLY ); + ret = read( fd, &temp, sizeof temp ); + printf( "temp=%d, ret=%d\n", temp, ret ); + close(fd); + return 0; +} +*/ + +/* +#include +#include +#include +int main() +{ + int fd, ret; + char buff[] = "LED_ON"; + fd = open( "/dev/mydev", O_WRONLY ); + ret = write( fd, buff, strlen(buff) ); + printf( "ret=%d\n", ret ); + close(fd); + return 0; +} +*/ +/* +#include +int main() +{ + int fd; + int flag=128; + fd = open( "/dev/mydev", O_WRONLY ); + write( fd, &flag, sizeof flag ); + close(fd); + return 0; +} +*/ diff --git a/02_day/list.c b/02_day/list.c new file mode 100644 index 0000000..3ce8148 --- /dev/null +++ b/02_day/list.c @@ -0,0 +1,67 @@ +#include +struct list_head { + struct list_head *next, *prev; +}; + +struct miscdevice { + int minor; + const char *name; + struct list_head list; +}; + + +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +static LIST_HEAD(misc_list); +static struct miscdevice misc = { + .minor = 24, + .name = "mydev", +}; + +int main() +{ + struct miscdevice *c; + list_add(&misc.list, &misc_list); + + list_for_each_entry(c, &misc_list, list) { + printf("minor=%d, name=%s\n", c->minor, c->name ); + } + return 0; +} + + + + + diff --git a/02_day/macro.c b/02_day/macro.c new file mode 100644 index 0000000..46b09d9 --- /dev/null +++ b/02_day/macro.c @@ -0,0 +1,12 @@ +#define __must_check __attribute__((warn_unused_result)) +int __must_check foo(void) +{ + return -1; +} + +int main() +{ + int ret; + ret = foo(); + return 0; +} diff --git a/02_day/misc_dev.c b/02_day/misc_dev.c new file mode 100644 index 0000000..cb90e95 --- /dev/null +++ b/02_day/misc_dev.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include //misc_register + +int my_open (struct inode *inode, struct file *filp) +{ + printk("my_open()\n"); + return 0; +} +int my_close(struct inode *inode, struct file *filp) +{ + printk("my_close()\n"); + return 0; +} + +static struct file_operations fops = +{ + .open = my_open, + .release = my_close, +}; + +static struct miscdevice misc = +{ + .minor = MISC_DYNAMIC_MINOR, + .name = "mydev", + .fops = &fops, +}; + +int my_init(void) +{ + misc_register( &misc ); + return 0; +} + +void my_exit(void) +{ + misc_deregister( &misc ); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/02_day/mknod.c b/02_day/mknod.c new file mode 100644 index 0000000..e722d4e --- /dev/null +++ b/02_day/mknod.c @@ -0,0 +1,10 @@ +#include +#include +#include +#include + +int main() +{ + mknod("mydev", S_IFCHR | 0666, (200<<8) | 0 ); + return 0; +} diff --git a/02_day/my_timer.c b/02_day/my_timer.c new file mode 100644 index 0000000..e8b8e11 --- /dev/null +++ b/02_day/my_timer.c @@ -0,0 +1,65 @@ +#if 1 +#include +#include +#include + +static struct timer_list timer; +void my_function(unsigned long data) +{ + printk("my_function(%lu)\n", data ); + timer.data = data+1; + mod_timer( &timer, jiffies + HZ); +} +int my_init(void) +{ + printk("init_module()\n"); + init_timer( &timer ); + timer.expires = jiffies + HZ; + timer.function = my_function; + timer.data = 0; + add_timer( &timer ); + return 0; +} + +void my_exit(void) +{ + del_timer( &timer ); + printk("cleanup_module()\n"); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); +#endif +#if 0 +#include +#include +#include + +static struct timer_list timer; +void my_function(unsigned long data) +{ + printk("my_function(%lu)\n", data ); +} +int my_init(void) +{ + printk("init_module()\n"); + init_timer( &timer ); + timer.expires = jiffies + 3*HZ; + timer.function = my_function; + timer.data = 0; + add_timer( &timer ); + return 0; +} + +void my_exit(void) +{ + del_timer( &timer ); + printk("cleanup_module()\n"); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); +#endif + diff --git a/02_day/rdwr_dev.c b/02_day/rdwr_dev.c new file mode 100644 index 0000000..83e46b2 --- /dev/null +++ b/02_day/rdwr_dev.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include //misc_register +#include //get_user, put_user + +int my_open (struct inode *inode, struct file *filp) +{ + printk("my_open()\n"); + return 0; +} +int my_close(struct inode *inode, struct file *filp) +{ + printk("my_close()\n"); + return 0; +} +ssize_t my_write (struct file *filp, const char __user *buff, + size_t size, loff_t *off) +{ + int ret, len; + char k_buff[5]; + printk("my_write()\n"); + len = (size>sizeof(k_buff)-1)? sizeof(k_buff)-1 : size; + + ret = copy_from_user( k_buff, buff, len ); + k_buff[len] = 0; + printk("%s\n", k_buff); + return len; +} +/* +ssize_t my_write (struct file *filp, const char __user *buff, + size_t size, loff_t *off) +{ + int i, len; + char k_buff[5]; + printk("my_write()\n"); + len = sizeof(k_buff)-1; + + for(i=0; i= len ) + break; + get_user( k_buff[i], buff+i); // k_buff[i] = *(buff+i); + } + k_buff[i] = 0; + printk("%s\n", k_buff); + return i; +} +*/ +/* +ssize_t my_write (struct file *filp, const char __user *buff, + size_t size, loff_t *off) +{ + int k_buff; + printk("my_write()\n"); + get_user( k_buff, (int*)buff ); // k_buff = *(int*)buff; + printk("%d\n", k_buff); + return sizeof(int); +} +*/ +ssize_t my_read (struct file *filp, char __user *buff, + size_t size, loff_t * off) +{ + char k_buff[] = "Hello user!!"; + int len = strlen(k_buff); + int ret; + + len = (size-1>len)? len: size-1; + printk("my_read()\n"); + ret = copy_to_user( buff, k_buff, len ); // *(buff+i) = k_buff[i]; + return len; +} +/* +ssize_t my_read (struct file *filp, char __user *buff, + size_t size, loff_t * off) +{ + char k_buff[] = "Hello user!!"; + int i; + printk("my_read()\n"); + for(i=0; k_buff[i]; i++) + { + if( i >= size-1 ) + break; + put_user( k_buff[i], buff+i ); // *(buff+i) = k_buff[i]; + } + return i; +} +*/ +/* +ssize_t my_read (struct file *filp, char __user *buff, + size_t size, loff_t * off) +{ + int temp=28; + printk("my_read()\n"); + put_user( temp, (int*)buff ); // *(int*)buff = temp; + return sizeof temp; +} +*/ +static struct file_operations fops = +{ + .open = my_open, + .release = my_close, + .write = my_write, + .read = my_read, +}; + +static struct miscdevice misc = +{ + .minor = MISC_DYNAMIC_MINOR, + .name = "mydev", + .fops = &fops, +}; + +int my_init(void) +{ + misc_register( &misc ); + return 0; +} + +void my_exit(void) +{ + misc_deregister( &misc ); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/03_day/.kernel_file.c.swp b/03_day/.kernel_file.c.swp new file mode 100644 index 0000000000000000000000000000000000000000..61275113e592fc3d81486659caa54c65d41015f6 GIT binary patch literal 12288 zcmeI2Uu)A)7{=duWs&(8#2ew5A*7`?*{1cPR?r&9uxn@6P6Q>S$w?cQoy0V89n<+8 z_5}nH)C+ID*K5CkUqHN6)O+8Pq%w5Fo81iG0}toq$?0?6_m|$3rmwFqF0reX%Yfq~ zz>B-0xAV3IU%CKM5X92{*YG`&j4!QvQJh%*&0xIW{%skk&FQmO^r}9ut?@{3-*i2n zSM2>hLp~880tZE48s_I_b(uD!TwrHT_YNwUa)>Y5jX?{;&2L{ zVVy_vTF>Y6)E{$xNfQwu0z`la5CI}U1c(3;AOb{y2oM1xa0m%l4#2r-fY&Jb|NrFo z|K}3`A5rg6&rv(5ZPX*wL(~fD6bev3jstu^y+nnm9;$*mi#moXppK$`;u+sj-%wvs zpHS~nZ&335S11}pfCvx)B0vO)01+SpM1Tkof&ZSsdf+5JH~H9$RkpsFE?BV!x$lYG zmka4HwQu#BhS^+f7_AjURTh?;3fk}#w%~E#Ig<=kUKFKYhiZ?JF=sK+=`K^J+z`y(KH7< zHh0&#aC_OjV{}?ZbCS2aQ_syhWc9l2F>4*;QUXDUr7%Tvtk}}}{XX{5Ht%)Xt>*nF zZL{0ywHi1#I>wDIW>>4#v_B2VVyyqriz31pLAE7r(^jis6VMuKXc9$jp&+blGKovGv&-zJw1|38 z6ufy9`~*_LlV3o+3AI-bf(U{a4+@_Bz1vM&niMZy3h%( z*}>BS*Fhm(Ea~ZYuPfq9O$g)r5rzMCHC^3W7?^QQ)N+~^{e`XSKcIv|BiZ3I*|F^C zkmospT~qUe)vX$EoDHyn|6`yP)d$Y)6Qd);SxR^^eL@~SH2r^aa~3wh2G{@_U;}J` z4X^<=zy`L3fhgz^4>8gm$!N!ud(WnO^2#?hzy{a=8(;%$fDNz#Hoykh02^QfY+xH2 zaPT|-`#nN@>c!yk`+xiY|L+Hc_z2#Dr(h1;1bL7HyTLB-bH5PZz*n#YUV-P}33v=1 zfh*uL7y-w@PVjl35Ffxx;DI~fHn0JHrW9k~1n32S_6qSE`~oXr8N2~6!87m_JOL3f zU=~zB2~2@=U<@1sN5K)$1Abu6D}d&{O!Mc94X^<=zy{a=8(;%$fDLRn1D;=NHI=Ov z+{lvNV*DWc&Wj}O>LgAN6fa-BG+ip#rQ$@Pa-(3SC$E*#2#fn7<+))M2Xu{UxM8G> zB~MX=8r>7~zFTXjx9FuWZemo_GFoQOC#}1-b#+8drlp1 z$;r)5QYlJAS5Vja{P0Ld4v&x1ZQgSR^7Eb@I1Ob7#*bi`>KR3+q*2>8j&3Lm_0}t6 zt|lTWD94~}w6-K=pfyUx4-{>v$gUfOyeJASIeGb-Jyp0~DU>oYyIR#?P3A0Uj$K%N zw=`{nR7;0$L#vu>`nnNk?hMv7?T2Jd$)uIICnvHWe}hb06DH^w<=9D$e$1w0-vsMp ziI<=~n6*Auqe%*Eh8lW_Z)@GG_uNPOc*CaLkepVsBX_*k?Fsxdw>atQYO{p_jK^o- zaio3lZoVVhs0ZD`o@YmkfeO2pt?gTsN;xzXe-_)Hrj8!!U6afyqgAtO`uIzNO8x?+ CQkVq* literal 0 HcmV?d00001 diff --git a/03_day/.my_memory.c.swp b/03_day/.my_memory.c.swp new file mode 100644 index 0000000000000000000000000000000000000000..5188e3a1421e7b3dd91fd9e1614feccc042bb4b4 GIT binary patch literal 12288 zcmeI2U2oe|7{||$m}FoB!4=%>kZqb1lGaJH(y2+MG|SqkY1TFABvgv!*(a$N$F>}& zOL-YD-+;Rb!52VGAQ*RCB7qR%4sp)~H(c@s_#fM8lQxK}N+3O!e)93-=bZESca9@f z^*!xweUraFS7bO|VC?fx-JNe9H`yyDV}a*|GW>6cW4psq?yen#L&I71M*o!mP!2d> z(DK){MQvfef2j9G-wO`sFc%$UfDD|WfnnImEnQ#>g}f$bxtw~Hzx3kH8BRz;lL0b7 z2FL&zAOmE843Ggb@Lw|!`sdjDDC()Cu%+aD?!-B{q!Sq+17v^yY=IR}0tN6g z`0FBL--9RM6EFe~z#UKpuK^A&fv3T57Z`gCz5tKF9=HPje2%eSz<1zd&;eyo0++yf z@H=Y%75oH#1V4Z$;A`*|_!2wXA{f*3QN(1ARPVkm-9_n0ov0;w zuG7V=-P+POYTM0PLv~b@%64^K->f(FcBQpZY1G%6S>9??R`sn)vtH%z#uv@o?d?i+ zBg>mRjkx2)TxKAQP^hV+$*>j!`)%QM)Yybv(zun*GUe!Etg(!bHZ9SyUBORRqcrk* zwNhQL>8o$FYptWq>9C@xd0r~@!IgrN!#&O!X`dm6rPcr3OD4l@r=KWHxVzEOo-mz@r#HI z8RoV%&XpT?x1jCG9w(O?i)y>3GqeORMc>iSCvV%_{>rIa1IM^GE8gw+v%) +#include +#include +#include //misc_register +#include +#include +#include + +static int temp; +static DECLARE_WAIT_QUEUE_HEAD(my_wait); + +int my_open (struct inode *inode, struct file *filp) +{ + temp = -999; + printk("my_open()\n"); + return 0; +} +int my_close(struct inode *inode, struct file *filp) +{ + printk("my_close()\n"); + return 0; +} + +irqreturn_t my_handler(int irq, void *id) +{ + printk("my_handler()\n"); + temp=23; + wake_up_interruptible(&my_wait); + return IRQ_HANDLED; +} + +ssize_t my_read (struct file *filp, char __user *buff, size_t size, + loff_t *off) +{ + printk("my_read()\n"); + if( temp == -999 ) + interruptible_sleep_on(&my_wait); + put_user( temp, (int*)buff ); + return 4; +} + +static struct file_operations fops = +{ + .open = my_open, + .release = my_close, + .read = my_read, +}; + +static struct miscdevice misc = +{ + .minor = MISC_DYNAMIC_MINOR, + .name = "mydev", + .fops = &fops, +}; + +int my_init(void) +{ + int ret; + unsigned long flags=IRQF_SHARED; + misc_register( &misc ); + flags |= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; + ret = request_irq(342, my_handler, flags, "MY_INT", my_handler); + return 0; +} + +void my_exit(void) +{ + free_irq( 342, my_handler); + misc_deregister( &misc ); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/03_day/ioctl_dev.c b/03_day/ioctl_dev.c new file mode 100644 index 0000000..a12096d --- /dev/null +++ b/03_day/ioctl_dev.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include //misc_register +#include +#include + +int my_open (struct inode *inode, struct file *filp) +{ + printk("my_open()\n"); + return 0; +} +int my_close(struct inode *inode, struct file *filp) +{ + printk("my_close()\n"); + return 0; +} +//#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) +#define LED_RATIO _IOW( 'm', 1, int ) + +static int ratio; + +long my_ioctl(struct file *filp, unsigned int cmd, unsigned long opt) +{ + unsigned int size; + int ret; + printk("my_ioctl()\n"); + + size = _IOC_SIZE(cmd); + + switch( cmd ) + { + case LED_RATIO: + if( size != sizeof(int)) + return -EINVAL; + + ret = copy_from_user( &ratio, (void*)opt, size); + printk("LED_RATIO, ratio=%d\n", ratio ); + break; + } + + return 0; +} +/* +//#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) +#define LED_RATIO _IO( 'm', 1 ) +static int ratio; + +long my_ioctl(struct file *filp, unsigned int cmd, unsigned long opt) +{ + printk("my_ioctl()\n"); + + if( _IOC_TYPE(cmd) != 'm' ) + return -EINVAL; + + if( _IOC_NR(cmd) != 1 ) + return -EINVAL; + + switch( cmd ) + { + case LED_RATIO: ratio = 128; + printk("LED_RATIO, ratio=%d\n", ratio ); + break; + } + + return 0; +} +*/ + +static struct file_operations fops = +{ + .open = my_open, + .release = my_close, + .unlocked_ioctl = my_ioctl, + .compat_ioctl = my_ioctl, +}; + +static struct miscdevice misc = +{ + .minor = MISC_DYNAMIC_MINOR, + .name = "mydev", + .fops = &fops, +}; + +int my_init(void) +{ + misc_register( &misc ); + return 0; +} + +void my_exit(void) +{ + misc_deregister( &misc ); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/03_day/jni/Android.mk b/03_day/jni/Android.mk new file mode 100644 index 0000000..70b5b29 --- /dev/null +++ b/03_day/jni/Android.mk @@ -0,0 +1,8 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_CFLAGS := -fPIE +LOCAL_LDFLAGS := -fPIE -pie +LOCAL_MODULE := myapp +LOCAL_SRC_FILES := blocking_app.c +include $(BUILD_EXECUTABLE) + diff --git a/03_day/jni/ioctl_app.c b/03_day/jni/ioctl_app.c new file mode 100644 index 0000000..e04d376 --- /dev/null +++ b/03_day/jni/ioctl_app.c @@ -0,0 +1,52 @@ +#if 1 +#include +#include +#include +#include +#include + +#define LED_RATIO _IOW( 'm', 1 , int) + +int main() +{ + int fd, ret; + int ratio; + char buff[10]; + printf("밝기 입력( 0-255 ) : "); + scanf("%d", &ratio ); + fd = open( "/dev/mydev", O_RDONLY ); + ret = ioctl(fd, LED_RATIO, &ratio); + if( ret < 0 ) + { + printf("ret=%d, errno=%d\n", ret, errno ); + return 0; + } + close(fd); + return 0; +} +#endif +#if 0 +#include +#include +#include +#include +#include + +#define LED_RATIO _IO( 'm', 1 ) + +int main() +{ + int fd, ret; + char buff[10]; + fd = open( "/dev/mydev", O_RDONLY ); + ret = ioctl(fd, LED_RATIO); + if( ret < 0 ) + { + printf("ret=%d, errno=%d\n", ret, errno ); + return 0; + } + close(fd); + return 0; +} +#endif + diff --git a/03_day/jni/mmap_app.c b/03_day/jni/mmap_app.c new file mode 100644 index 0000000..6acd94d --- /dev/null +++ b/03_day/jni/mmap_app.c @@ -0,0 +1,21 @@ +#if 1 +#include +#include +#include +#include + +int main() +{ + int fd; + char *p; + fd = open("/dev/mydev", O_RDWR ); + p = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + strcpy( p , "hello world\n"); + printf("%s\n", p ); + munmap(p, 4096); + close(fd); + return 0; +} + +#endif + diff --git a/03_day/jni/myapp.c b/03_day/jni/myapp.c new file mode 100644 index 0000000..d8c9bfb --- /dev/null +++ b/03_day/jni/myapp.c @@ -0,0 +1,10 @@ +#include +int main() +{ + int fd; + fd = open( "/sys/devices/virtual/misc/mydev/uevent", O_WRONLY ); + write( fd, "add\n", 4 ); + close(fd); + return 0; +} + diff --git a/03_day/jni/poll_app.c b/03_day/jni/poll_app.c new file mode 100644 index 0000000..49d783b --- /dev/null +++ b/03_day/jni/poll_app.c @@ -0,0 +1,59 @@ +#if 1 +#include +#include +#include + +int main() +{ + int fd, ret; + int temp; + char buff[1024]; + struct pollfd fds[2]; + fd = open( "/dev/mydev", O_RDONLY ); + fds[0].fd = 0 ; + fds[0].events = POLLIN; + fds[1].fd = fd ; + fds[1].events = POLLIN; + + poll( fds, 2, -1 ); + + if( fds[0].revents & POLLIN ) + { + read( 0, buff, sizeof buff ); + buff[ret-1] = 0; + printf("buff=%s\n", buff ); + } + if( fds[1].revents & POLLIN ) + { + read( fd, &temp, sizeof temp ); + printf("temp=%d\n", temp ); + } + close(fd); + return 0; +} +#endif +#if 0 +#include +#include +#include +#include +#include + +#define LED_RATIO _IO( 'm', 1 ) + +int main() +{ + int fd, ret; + char buff[10]; + fd = open( "/dev/mydev", O_RDONLY ); + ret = ioctl(fd, LED_RATIO); + if( ret < 0 ) + { + printf("ret=%d, errno=%d\n", ret, errno ); + return 0; + } + close(fd); + return 0; +} +#endif + diff --git a/03_day/jni/rdwr_app.c b/03_day/jni/rdwr_app.c new file mode 100644 index 0000000..0075ca7 --- /dev/null +++ b/03_day/jni/rdwr_app.c @@ -0,0 +1,57 @@ +#include +#include +#include +int main() +{ + int fd, ret; + char buff[10]; + fd = open( "/dev/mydev", O_RDONLY ); + ret = read( fd, buff, sizeof buff ); + buff[ret] = 0; + printf( "buff[%s], ret=%d\n", buff, ret ); + close(fd); + return 0; +} +/* +#include +#include +#include +int main() +{ + int fd, ret; + int temp; + fd = open( "/dev/mydev", O_RDONLY ); + ret = read( fd, &temp, sizeof temp ); + printf( "temp=%d, ret=%d\n", temp, ret ); + close(fd); + return 0; +} +*/ + +/* +#include +#include +#include +int main() +{ + int fd, ret; + char buff[] = "LED_ON"; + fd = open( "/dev/mydev", O_WRONLY ); + ret = write( fd, buff, strlen(buff) ); + printf( "ret=%d\n", ret ); + close(fd); + return 0; +} +*/ +/* +#include +int main() +{ + int fd; + int flag=128; + fd = open( "/dev/mydev", O_WRONLY ); + write( fd, &flag, sizeof flag ); + close(fd); + return 0; +} +*/ diff --git a/03_day/kernel_file.c b/03_day/kernel_file.c new file mode 100644 index 0000000..65ecbd7 --- /dev/null +++ b/03_day/kernel_file.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +// /data/aaa +int my_init(void) { + char *buff; + struct file *filp; + int ret; + filp = filp_open( "/data/bbb", O_WRONLY|O_TRUNC|O_CREAT, 0666 ); + if( filp == 0 ) + return 0; + buff = (char*)__get_free_pages( GFP_KERNEL, 0 ); + strcpy(buff, "hello world"); + ret = kernel_write( filp, buff, strlen(buff), 0 ); + printk("ret=%d\n", ret ); + free_pages( (unsigned long)buff, 0 ); + filp_close( filp, 0 ); + return 0; +} + +void my_exit(void) +{ +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/03_day/mmap.c b/03_day/mmap.c new file mode 100644 index 0000000..1e78783 --- /dev/null +++ b/03_day/mmap.c @@ -0,0 +1,34 @@ +#if 1 +#include +#include +#include +#include +int main() +{ + int fd; + char *p; + printf("main=%p\n", main); + fd = open("aaa", O_RDWR | O_TRUNC | O_CREAT , 0666 ); + ftruncate(fd, 1024); + p = mmap(0, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + strcpy( p , "hello world\n"); + //printf("%s\n", p ); + munmap(p, 1024); + close(fd); + return 0; +} +#endif + +#if 0 +#include +int main() +{ + //mmap(); + + int fd; + fd = open("aaa", O_WRONLY | O_TRUNC | O_CREAT , 0666 ); + write( fd, "hello world", 11 ); + close(fd); + return 0; +} +#endif diff --git a/03_day/mmap_dev.c b/03_day/mmap_dev.c new file mode 100644 index 0000000..e822556 --- /dev/null +++ b/03_day/mmap_dev.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include //misc_register +#include +#include +#include + +int my_open (struct inode *inode, struct file *filp) +{ + printk("my_open()\n"); + return 0; +} +int my_close(struct inode *inode, struct file *filp) +{ + printk("my_close()\n"); + return 0; +} + +int my_mmap(struct file *filp, struct vm_area_struct *vma) +{ + unsigned long pfn; + unsigned long page; + printk("my_mmap()\n"); + page = __get_free_pages( GFP_KERNEL, 0 ); + pfn = __pa( page ); + remap_pfn_range(vma, vma->vm_start, + pfn>>12, 1<<12, vma->vm_page_prot); + return 0; +} + +static struct file_operations fops = +{ + .open = my_open, + .release = my_close, + .mmap = my_mmap, +}; + +static struct miscdevice misc = +{ + .minor = MISC_DYNAMIC_MINOR, + .name = "mydev", + .fops = &fops, +}; + +int my_init(void) +{ + misc_register( &misc ); + return 0; +} + +void my_exit(void) +{ + misc_deregister( &misc ); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/03_day/my_int.c b/03_day/my_int.c new file mode 100644 index 0000000..b95001b --- /dev/null +++ b/03_day/my_int.c @@ -0,0 +1,28 @@ +#include +#include +#include + +irqreturn_t my_handler(int irq, void *id) +{ + printk("my_handler()\n"); + return IRQ_HANDLED; +} + +int my_init(void) +{ + int ret; + unsigned long flags=IRQF_SHARED; + flags |= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; + ret = request_irq(342, my_handler, flags, "MY_INT", my_handler); + return 0; +} + +void my_exit(void) +{ + free_irq( 342, my_handler); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/03_day/my_memory.c b/03_day/my_memory.c new file mode 100644 index 0000000..a2084c8 --- /dev/null +++ b/03_day/my_memory.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include + +struct my_struct +{ + char name[20]; + int id; +}; + +int my_init(void) +{ + char *p; + struct my_struct *task; + struct kmem_cache *my_struct_cachep; + p = (char*)__get_free_pages( GFP_KERNEL, 0 ); + p[4095] = 'x'; + printk("%c\n", p[4095]); + free_pages((unsigned long)p, 0); + + p = (char*)kmalloc( 64, GFP_KERNEL); + p[63] = 'x'; + printk("%c\n", p[63]); + kfree(p); + +#define L1_CACHE_SHIFT 6 +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +#define ARCH_MIN_TASKALIGN L1_CACHE_BYTES + + my_struct_cachep = + kmem_cache_create("my_struct", sizeof(struct my_struct), + ARCH_MIN_TASKALIGN, SLAB_PANIC | SLAB_NOTRACK, NULL); + task = kmem_cache_alloc( my_struct_cachep, GFP_KERNEL); + strcpy( task->name, "kji"); + task->id = 1234; + printk("%s, %d\n", task->name, task->id); + kmem_cache_free( my_struct_cachep, task); + kmem_cache_destroy( my_struct_cachep ); + + p = vmalloc( 8192 * 1024 ); + p[8192 * 1024-1] = 'x'; + printk("%c\n", p[8192 * 1024-1] ); + vfree( p ); + return 0; +} + +void my_exit(void) +{ +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/03_day/poll_1.c b/03_day/poll_1.c new file mode 100644 index 0000000..2ff716b --- /dev/null +++ b/03_day/poll_1.c @@ -0,0 +1,74 @@ +#if 1 +#include +#include +#include +int main() +{ + char buff[1024]; + int ret; + int fd; + struct pollfd fds[2]; + // mkfifo myfifo + fd = open("myfifo", O_RDWR ); + while(1) + { + fds[0].fd = 0; + fds[0].events = POLLIN; + fds[1].fd = fd; + fds[1].events = POLLIN; + poll( fds, 2, -1); + if( fds[0].revents & POLLIN ) + { + ret = read(0, buff, sizeof buff ); + buff[ret-1] = 0; + printf("키보드 [%s]\n", buff ); + } + + if( fds[1].revents & POLLIN ) + { + ret = read(fd, buff, sizeof buff ); + buff[ret-1] = 0; + printf("myfifo [%s]\n", buff ); + } + } + close(fd); + return 0; +} +#endif +#if 0 +#include +#include +int main() +{ + char buff[1024]; + int ret; + int fd; + // mkfifo myfifo + fd = open("myfifo", O_RDWR ); + while(1) + { + ret = read(0, buff, sizeof buff ); + buff[ret-1] = 0; + printf("키보드 [%s]\n", buff ); + + ret = read(fd, buff, sizeof buff ); + buff[ret-1] = 0; + printf("myfifo [%s]\n", buff ); + } + close(fd); + return 0; +} +#endif + + +#if 0 +#include +int main() +{ + char buff[1024]; + int ret; + ret = read(0, buff, sizeof buff ); + write( 1, buff, ret ); + return 0; +} +#endif diff --git a/03_day/poll_dev.c b/03_day/poll_dev.c new file mode 100644 index 0000000..4a8f9b7 --- /dev/null +++ b/03_day/poll_dev.c @@ -0,0 +1,87 @@ +#include +#include +#include +#include //misc_register +#include +#include +#include +#include + +static int temp; +static DECLARE_WAIT_QUEUE_HEAD(my_wait); +static struct timer_list timer; + +void my_function(unsigned long data) +{ + printk("my_function(%lu)\n", data ); + temp = 28; + wake_up_interruptible( &my_wait ); +} +int my_open (struct inode *inode, struct file *filp) +{ + init_timer( &timer ); + timer.expires = jiffies + 3*HZ; + timer.function = my_function; + timer.data = 0; + add_timer( &timer ); + temp = -999; + printk("my_open()\n"); + return 0; +} +int my_close(struct inode *inode, struct file *filp) +{ + printk("my_close()\n"); + return 0; +} + + +unsigned int my_poll(struct file *filp, struct poll_table_struct *table) +{ + unsigned int mask=0; + printk("my_poll()\n"); + + poll_wait(filp, &my_wait, table); + if( temp != -999 ) + mask = POLLIN; + return mask; +} + +ssize_t my_read (struct file *filp, char __user *buff, size_t size, + loff_t *off) +{ + printk("my_read()\n"); + put_user( temp, (int*)buff ); + return 4; +} + +static struct file_operations fops = +{ + .open = my_open, + .release = my_close, + .poll = my_poll, + .read = my_read, +}; + +static struct miscdevice misc = +{ + .minor = MISC_DYNAMIC_MINOR, + .name = "mydev", + .fops = &fops, +}; + +int my_init(void) +{ + misc_register( &misc ); + return 0; +} + +void my_exit(void) +{ + del_timer( &timer ); + misc_deregister( &misc ); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/03_day/type.c b/03_day/type.c new file mode 100644 index 0000000..b2b9838 --- /dev/null +++ b/03_day/type.c @@ -0,0 +1,10 @@ +#include +int main() +{ + int a[4]; + int *p = a; + printf("sizeof(a) =%lu\n", sizeof(a)); + printf("sizeof(int[4])=%lu\n", sizeof(int[4])); + printf("sizeof(p) =%lu\n", sizeof(p)); + printf("sizeof(int*) =%lu\n", sizeof(int*)); +} diff --git a/04_day/.input_dev.c.swp b/04_day/.input_dev.c.swp new file mode 100644 index 0000000000000000000000000000000000000000..d7aba38ad2d74c52bdd38d3cf1e450c5fe89fd0c GIT binary patch literal 12288 zcmeI2%Wl&^6ov?8*{^*drt=UI4@fgv6FDEcnNlsv!n8EI>MzK4m;}=A1MC8Cyy+Q~7#ng!gv# zFkCwr+qdG>zOGc*lO@Jn$C0Z0PnTud{?d`U=}KR>&N!HveBDwGbKUu_WBKFxo}6hn zeW^9XVyBU8Pral7DeyNH*vgJ}cjcAGL+OKj_paLCbWXlV0aAbzAO%PPQh*d71xNu> z;2&2&HaD=_$Z=zoXYe}!+8d(#_%pht4^n^>AO%PPQh*d71xNu>fD|AFNC8rS6!;Gn z&>M_(Y+`KhW+adQ|KsofpSLr%3Z8)nzyWp82RJwYzHejf8+Z#=!Bg-E+y!^QI2Z*d zz<%&?D{R3kcmrO5=U@dq1k>O&*a<#ufjxK$?t>oi1v!2I@4-9p8oUCJ!98#lTmhHC z5aS=4XZQNL=a z{*lqaTDho|OJ|FfiDD)_JXTJlo84ro@RX}>yJE)lq;S=NSJMy~cnyYNmYQ~j&`ftB z!;kj%WmUjg-ELSg_M1PA_jI?6H=JuWEUvRf$85xzX4Fkb5Zx8hcWs_W5Hxv#yJEo? zo(!V32g~wlOP}$wJUue0l`0ps+E}_JUYJjUtAxDToDGg%thBm|(oY3Z`HccERmX?4 z3)Rx_aIvaYOB1EaFu&2-J2X%(qkC;dp}@b9m!&k#6H=Q}MLS=d)as+<+DNfB7OX6o zex!d+EMr`WooK95|D$=auEG6!GqD&sjjN3cg!$^0mt0K4M>@C~ITDHH)$#2FP{W3UA5<;_R0iJYy1Bu1Q(fQ%HT6lsF znYLm14Z%+Zr`*Fs>z%Xx2?KbzUB4+?2X${g=j(ibazcRf0_{X&zqhRz9=w@ d^IT4KpoHN&q%HV#qVqZ7+QLc-8@|WX$PaWz<01e6 literal 0 HcmV?d00001 diff --git a/04_day/Makefile b/04_day/Makefile new file mode 100644 index 0000000..9d8b3e9 --- /dev/null +++ b/04_day/Makefile @@ -0,0 +1,10 @@ +obj-m = my_work.o + +KDIR = /usr/src/tegra +PWD = $(shell pwd) + +default: + make -C $(KDIR) SUBDIRS=$(PWD) modules + +clean: + make -C $(KDIR) SUBDIRS=$(PWD) clean diff --git a/04_day/flex.c b/04_day/flex.c new file mode 100644 index 0000000..d56a47f --- /dev/null +++ b/04_day/flex.c @@ -0,0 +1,34 @@ +#if 1 +#include +struct aaa +{ + int count; + int flag; + int data[]; +}; + +int main() +{ + struct aaa *p; + p = malloc( sizeof(struct aaa) + sizeof(int)*100 ); + p->count = 0; + p->data[0] = 10; + return 0; +} +#endif + +#if 0 +#include +struct aaa +{ + int a; + int b[]; +}; + +int main() +{ + struct aaa a; + printf("sizeof(a)=%lu\n", sizeof a ); + return 0; +} +#endif diff --git a/04_day/input_dev.c b/04_day/input_dev.c new file mode 100644 index 0000000..b4856c9 --- /dev/null +++ b/04_day/input_dev.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include //misc_register +#include +#include +#include +#include + +static struct input_dev *my_input; + +irqreturn_t my_handler_up(int irq, void *id) +{ + printk("my_handler_up()\n"); + input_sync(my_input); + return IRQ_HANDLED; +} +irqreturn_t my_handler_down(int irq, void *id) +{ + static int value=0; + printk("my_handler_down()\n"); + input_report_key(my_input, KEY_VOLUMEDOWN, value^=1); + return IRQ_HANDLED; +} + +int my_init(void) +{ + int ret; + unsigned long flags=IRQF_SHARED; + my_input = input_allocate_device(); + __set_bit( EV_KEY, my_input->evbit); + __set_bit( KEY_VOLUMEDOWN, my_input->keybit); + __set_bit( KEY_VOLUMEUP, my_input->keybit); + + ret = input_register_device(my_input); + flags |= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; + ret = request_irq(342, my_handler_down, flags, "MY_INT_DOWN", my_handler_down); + ret = request_irq(379, my_handler_up, flags, "MY_INT_UP", my_handler_up); + return 0; +} + +void my_exit(void) +{ + free_irq( 342, my_handler_down); + free_irq( 379, my_handler_up); + input_unregister_device(my_input); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/04_day/jni/Android.mk b/04_day/jni/Android.mk new file mode 100644 index 0000000..09dec16 --- /dev/null +++ b/04_day/jni/Android.mk @@ -0,0 +1,8 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_CFLAGS := -fPIE +LOCAL_LDFLAGS := -fPIE -pie +LOCAL_MODULE := myapp +LOCAL_SRC_FILES := input_app.c +include $(BUILD_EXECUTABLE) + diff --git a/04_day/jni/input_app.c b/04_day/jni/input_app.c new file mode 100644 index 0000000..3d5370d --- /dev/null +++ b/04_day/jni/input_app.c @@ -0,0 +1,23 @@ +#if 1 +#include +#include +#include +#include + +int main() +{ + int i; + int fd, ret; + struct input_event events[64]; + fd = open( "/dev/input/event4", O_RDONLY ); + while (ret = read( fd, events, sizeof events )) + { + for( i=0 ; i<(ret/(int)sizeof(struct input_event)); i++ ) + printf("type=%d, code=%d, value=%d\n", + events[i].type, events[i].code, events[i].value); + } + close(fd); + return 0; +} +#endif + diff --git a/04_day/jni/queue_app.c b/04_day/jni/queue_app.c new file mode 100644 index 0000000..02634b4 --- /dev/null +++ b/04_day/jni/queue_app.c @@ -0,0 +1,21 @@ +#if 1 +#include +#include +#include + +int main() +{ + int i; + int fd, ret; + int temp[64]; + fd = open( "/dev/mydev", O_RDONLY ); + while (ret = read( fd, temp, sizeof temp )) + { + for( i=0 ; i<(ret/(int)sizeof(int)); i++ ) + printf("temp[%d] = %d\n", i, temp[i] ); + } + close(fd); + return 0; +} +#endif + diff --git a/04_day/my_work.c b/04_day/my_work.c new file mode 100644 index 0000000..92f3de8 --- /dev/null +++ b/04_day/my_work.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include + +static struct work_struct work; + +irqreturn_t my_handler(int irq, void *id) +{ + printk("my_handler()\n"); + schedule_work( &work ); + return IRQ_HANDLED; +} +void my_work_handler(struct work_struct *work) +{ + printk("my_work_handler()\n"); +} + +int my_init(void) +{ + int ret; + unsigned long flags=IRQF_SHARED; + flags |= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; + ret = request_irq(342, my_handler, flags, "MY_INT", my_handler); + INIT_WORK(&work, my_work_handler); + return 0; +} + +void my_exit(void) +{ + free_irq( 342, my_handler); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/04_day/queue.c b/04_day/queue.c new file mode 100644 index 0000000..2538ff8 --- /dev/null +++ b/04_day/queue.c @@ -0,0 +1,48 @@ +#include +typedef struct +{ + int queue[64]; + int head; + int tail; + int count; +} QUEUE; + +void init( QUEUE *q ) +{ + q->head = 0; + q->tail = 0; + q->count = 0; +} +void put( QUEUE *q, int data ) +{ + q->queue[q->head] = data; + q->head = (q->head+1)%64; + q->count++; +} +int get( QUEUE *q ) +{ + int temp; + temp = q->queue[q->tail]; + q->tail = (q->tail+1)%64; + q->count--; + return temp; +} +int is_empty( QUEUE *q ) +{ + return q->count == 0 ; +} +int main() +{ + QUEUE q; + init( &q ); + put( &q, 1 ); + put( &q, 2 ); + put( &q, 3 ); + while( !is_empty( &q ) ) + printf("%d\n", get(&q) ); + return 0; +} + + + + diff --git a/04_day/queue_dev.c b/04_day/queue_dev.c new file mode 100644 index 0000000..599d76d --- /dev/null +++ b/04_day/queue_dev.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include //misc_register +#include +#include +#include +#include + +typedef struct +{ + int queue[64]; + int head; + int tail; + int count; +} QUEUE; +static QUEUE queue; +static DECLARE_WAIT_QUEUE_HEAD(my_wait); + + +void init( QUEUE *q ) +{ + q->head = 0; + q->tail = 0; + q->count = 0; +} +void put( QUEUE *q, int data ) +{ + q->queue[q->head] = data; + q->head = (q->head+1)%64; + q->count++; +} +int get( QUEUE *q ) +{ + int temp; + temp = q->queue[q->tail]; + q->tail = (q->tail+1)%64; + q->count--; + return temp; +} +int is_empty( QUEUE *q ) +{ + return q->count == 0 ; +} + +int my_open (struct inode *inode, struct file *filp) +{ + init(&queue); + printk("my_open()\n"); + return 0; +} +int my_close(struct inode *inode, struct file *filp) +{ + printk("my_close()\n"); + return 0; +} + +irqreturn_t my_handler_up(int irq, void *id) +{ + printk("my_handler_up()\n"); + wake_up_interruptible(&my_wait); + return IRQ_HANDLED; +} +irqreturn_t my_handler_down(int irq, void *id) +{ + printk("my_handler_down()\n"); + put( &queue, KEY_VOLUMEDOWN ); + return IRQ_HANDLED; +} + +ssize_t my_read (struct file *filp, char __user *buff, size_t size, + loff_t *off) +{ + int i; + int *p = (int*)buff; + printk("my_read()\n"); + if( is_empty(&queue) ) + interruptible_sleep_on(&my_wait); + + for(i=0; !is_empty(&queue); i++ ) + put_user( get(&queue) , p+i); + return 4*i; +} + +static struct file_operations fops = +{ + .open = my_open, + .release = my_close, + .read = my_read, +}; + +static struct miscdevice misc = +{ + .minor = MISC_DYNAMIC_MINOR, + .name = "mydev", + .fops = &fops, +}; + +int my_init(void) +{ + int ret; + unsigned long flags=IRQF_SHARED; + misc_register( &misc ); + flags |= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; + ret = request_irq(342, my_handler_down, flags, "MY_INT_DOWN", my_handler_down); + ret = request_irq(379, my_handler_up, flags, "MY_INT_UP", my_handler_up); + return 0; +} + +void my_exit(void) +{ + free_irq( 342, my_handler_down); + free_irq( 379, my_handler_up); + misc_deregister( &misc ); +} + +MODULE_LICENSE("GPL"); +module_init( my_init ); +module_exit( my_exit ); + diff --git a/05_day/Makefile b/05_day/Makefile new file mode 100644 index 0000000..0e4ad37 --- /dev/null +++ b/05_day/Makefile @@ -0,0 +1,10 @@ +obj-m = kobject-example.o + +KDIR = /usr/src/tegra +PWD = $(shell pwd) + +default: + make -C $(KDIR) SUBDIRS=$(PWD) modules + +clean: + make -C $(KDIR) SUBDIRS=$(PWD) clean diff --git a/05_day/jni/Android.mk b/05_day/jni/Android.mk new file mode 100644 index 0000000..09dec16 --- /dev/null +++ b/05_day/jni/Android.mk @@ -0,0 +1,8 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_CFLAGS := -fPIE +LOCAL_LDFLAGS := -fPIE -pie +LOCAL_MODULE := myapp +LOCAL_SRC_FILES := input_app.c +include $(BUILD_EXECUTABLE) + diff --git a/05_day/jni/input_app.c b/05_day/jni/input_app.c new file mode 100644 index 0000000..3d5370d --- /dev/null +++ b/05_day/jni/input_app.c @@ -0,0 +1,23 @@ +#if 1 +#include +#include +#include +#include + +int main() +{ + int i; + int fd, ret; + struct input_event events[64]; + fd = open( "/dev/input/event4", O_RDONLY ); + while (ret = read( fd, events, sizeof events )) + { + for( i=0 ; i<(ret/(int)sizeof(struct input_event)); i++ ) + printf("type=%d, code=%d, value=%d\n", + events[i].type, events[i].code, events[i].value); + } + close(fd); + return 0; +} +#endif + diff --git a/05_day/jni/queue_app.c b/05_day/jni/queue_app.c new file mode 100644 index 0000000..02634b4 --- /dev/null +++ b/05_day/jni/queue_app.c @@ -0,0 +1,21 @@ +#if 1 +#include +#include +#include + +int main() +{ + int i; + int fd, ret; + int temp[64]; + fd = open( "/dev/mydev", O_RDONLY ); + while (ret = read( fd, temp, sizeof temp )) + { + for( i=0 ; i<(ret/(int)sizeof(int)); i++ ) + printf("temp[%d] = %d\n", i, temp[i] ); + } + close(fd); + return 0; +} +#endif + diff --git a/05_day/kobject-example.c b/05_day/kobject-example.c new file mode 100644 index 0000000..86ea0c3 --- /dev/null +++ b/05_day/kobject-example.c @@ -0,0 +1,137 @@ +/* + * Sample kobject implementation + * + * Copyright (C) 2004-2007 Greg Kroah-Hartman + * Copyright (C) 2007 Novell Inc. + * + * Released under the GPL version 2 only. + * + */ +#include +#include +#include +#include +#include + +/* + * This module shows how to create a simple subdirectory in sysfs called + * /sys/kernel/kobject-example In that directory, 3 files are created: + * "foo", "baz", and "bar". If an integer is written to these files, it can be + * later read out of it. + */ + +static int foo; +static int baz; +static int bar; + +/* + * The "foo" file where a static variable is read from and written to. + */ +static ssize_t foo_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", foo); +} + +static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + sscanf(buf, "%du", &foo); + return count; +} + +static struct kobj_attribute foo_attribute = + __ATTR(foo, 0666, foo_show, foo_store); + +/* + * More complex function where we determine which variable is being accessed by + * looking at the attribute for the "baz" and "bar" files. + */ +static ssize_t b_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + int var; + + if (strcmp(attr->attr.name, "baz") == 0) + var = baz; + else + var = bar; + return sprintf(buf, "%d\n", var); +} + +static ssize_t b_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int var; + + sscanf(buf, "%du", &var); + if (strcmp(attr->attr.name, "baz") == 0) + baz = var; + else + bar = var; + return count; +} + +static struct kobj_attribute baz_attribute = + __ATTR(baz, 0666, b_show, b_store); +static struct kobj_attribute bar_attribute = + __ATTR(bar, 0666, b_show, b_store); + + +/* + * Create a group of attributes so that we can create and destroy them all + * at once. + */ +static struct attribute *attrs[] = { + &foo_attribute.attr, + &baz_attribute.attr, + &bar_attribute.attr, + NULL, /* need to NULL terminate the list of attributes */ +}; + +/* + * An unnamed attribute group will put all of the attributes directly in + * the kobject directory. If we specify a name, a subdirectory will be + * created for the attributes with the directory being the name of the + * attribute group. + */ +static struct attribute_group attr_group = { + .attrs = attrs, +}; + +static struct kobject *example_kobj; + +static int __init example_init(void) +{ + int retval; + + /* + * Create a simple kobject with the name of "kobject_example", + * located under /sys/kernel/ + * + * As this is a simple directory, no uevent will be sent to + * userspace. That is why this function should not be used for + * any type of dynamic kobjects, where the name and number are + * not known ahead of time. + */ + example_kobj = kobject_create_and_add("kobject_example", kernel_kobj); + if (!example_kobj) + return -ENOMEM; + + /* Create the files associated with this kobject */ + retval = sysfs_create_group(example_kobj, &attr_group); + if (retval) + kobject_put(example_kobj); + + return retval; +} + +static void __exit example_exit(void) +{ + kobject_put(example_kobj); +} + +module_init(example_init); +module_exit(example_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/05_day/kset-example.c b/05_day/kset-example.c new file mode 100644 index 0000000..d0c687f --- /dev/null +++ b/05_day/kset-example.c @@ -0,0 +1,279 @@ +/* + * Sample kset and ktype implementation + * + * Copyright (C) 2004-2007 Greg Kroah-Hartman + * Copyright (C) 2007 Novell Inc. + * + * Released under the GPL version 2 only. + * + */ +#include +#include +#include +#include +#include +#include + +/* + * This module shows how to create a kset in sysfs called + * /sys/kernel/kset-example + * Then tree kobjects are created and assigned to this kset, "foo", "baz", + * and "bar". In those kobjects, attributes of the same name are also + * created and if an integer is written to these files, it can be later + * read out of it. + */ + + +/* + * This is our "object" that we will create a few of and register them with + * sysfs. + */ +struct foo_obj { + struct kobject kobj; + int foo; + int baz; + int bar; +}; +#define to_foo_obj(x) container_of(x, struct foo_obj, kobj) + +/* a custom attribute that works just for a struct foo_obj. */ +struct foo_attribute { + struct attribute attr; + ssize_t (*show)(struct foo_obj *foo, struct foo_attribute *attr, char *buf); + ssize_t (*store)(struct foo_obj *foo, struct foo_attribute *attr, const char *buf, size_t count); +}; +#define to_foo_attr(x) container_of(x, struct foo_attribute, attr) + +/* + * The default show function that must be passed to sysfs. This will be + * called by sysfs for whenever a show function is called by the user on a + * sysfs file associated with the kobjects we have registered. We need to + * transpose back from a "default" kobject to our custom struct foo_obj and + * then call the show function for that specific object. + */ +static ssize_t foo_attr_show(struct kobject *kobj, + struct attribute *attr, + char *buf) +{ + struct foo_attribute *attribute; + struct foo_obj *foo; + + attribute = to_foo_attr(attr); + foo = to_foo_obj(kobj); + + if (!attribute->show) + return -EIO; + + return attribute->show(foo, attribute, buf); +} + +/* + * Just like the default show function above, but this one is for when the + * sysfs "store" is requested (when a value is written to a file.) + */ +static ssize_t foo_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, size_t len) +{ + struct foo_attribute *attribute; + struct foo_obj *foo; + + attribute = to_foo_attr(attr); + foo = to_foo_obj(kobj); + + if (!attribute->store) + return -EIO; + + return attribute->store(foo, attribute, buf, len); +} + +/* Our custom sysfs_ops that we will associate with our ktype later on */ +static const struct sysfs_ops foo_sysfs_ops = { + .show = foo_attr_show, + .store = foo_attr_store, +}; + +/* + * The release function for our object. This is REQUIRED by the kernel to + * have. We free the memory held in our object here. + * + * NEVER try to get away with just a "blank" release function to try to be + * smarter than the kernel. Turns out, no one ever is... + */ +static void foo_release(struct kobject *kobj) +{ + struct foo_obj *foo; + + foo = to_foo_obj(kobj); + kfree(foo); +} + +/* + * The "foo" file where the .foo variable is read from and written to. + */ +static ssize_t foo_show(struct foo_obj *foo_obj, struct foo_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", foo_obj->foo); +} + +static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr, + const char *buf, size_t count) +{ + sscanf(buf, "%du", &foo_obj->foo); + return count; +} + +static struct foo_attribute foo_attribute = + __ATTR(foo, 0666, foo_show, foo_store); + +/* + * More complex function where we determine which variable is being accessed by + * looking at the attribute for the "baz" and "bar" files. + */ +static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr, + char *buf) +{ + int var; + + if (strcmp(attr->attr.name, "baz") == 0) + var = foo_obj->baz; + else + var = foo_obj->bar; + return sprintf(buf, "%d\n", var); +} + +static ssize_t b_store(struct foo_obj *foo_obj, struct foo_attribute *attr, + const char *buf, size_t count) +{ + int var; + + sscanf(buf, "%du", &var); + if (strcmp(attr->attr.name, "baz") == 0) + foo_obj->baz = var; + else + foo_obj->bar = var; + return count; +} + +static struct foo_attribute baz_attribute = + __ATTR(baz, 0666, b_show, b_store); +static struct foo_attribute bar_attribute = + __ATTR(bar, 0666, b_show, b_store); + +/* + * Create a group of attributes so that we can create and destroy them all + * at once. + */ +static struct attribute *foo_default_attrs[] = { + &foo_attribute.attr, + &baz_attribute.attr, + &bar_attribute.attr, + NULL, /* need to NULL terminate the list of attributes */ +}; + +/* + * Our own ktype for our kobjects. Here we specify our sysfs ops, the + * release function, and the set of default attributes we want created + * whenever a kobject of this type is registered with the kernel. + */ +static struct kobj_type foo_ktype = { + .sysfs_ops = &foo_sysfs_ops, + .release = foo_release, + .default_attrs = foo_default_attrs, +}; + +static struct kset *example_kset; +static struct foo_obj *foo_obj; +static struct foo_obj *bar_obj; +static struct foo_obj *baz_obj; + +static struct foo_obj *create_foo_obj(const char *name) +{ + struct foo_obj *foo; + int retval; + + /* allocate the memory for the whole object */ + foo = kzalloc(sizeof(*foo), GFP_KERNEL); + if (!foo) + return NULL; + + /* + * As we have a kset for this kobject, we need to set it before calling + * the kobject core. + */ + foo->kobj.kset = example_kset; + + /* + * Initialize and add the kobject to the kernel. All the default files + * will be created here. As we have already specified a kset for this + * kobject, we don't have to set a parent for the kobject, the kobject + * will be placed beneath that kset automatically. + */ + retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name); + if (retval) { + kobject_put(&foo->kobj); + return NULL; + } + + /* + * We are always responsible for sending the uevent that the kobject + * was added to the system. + */ + kobject_uevent(&foo->kobj, KOBJ_ADD); + + return foo; +} + +static void destroy_foo_obj(struct foo_obj *foo) +{ + kobject_put(&foo->kobj); +} + +static int __init example_init(void) +{ + /* + * Create a kset with the name of "kset_example", + * located under /sys/kernel/ + */ + example_kset = kset_create_and_add("kset_example", NULL, kernel_kobj); + if (!example_kset) + return -ENOMEM; + + /* + * Create three objects and register them with our kset + */ + foo_obj = create_foo_obj("foo"); + if (!foo_obj) + goto foo_error; + + bar_obj = create_foo_obj("bar"); + if (!bar_obj) + goto bar_error; + + baz_obj = create_foo_obj("baz"); + if (!baz_obj) + goto baz_error; + + return 0; + +baz_error: + destroy_foo_obj(bar_obj); +bar_error: + destroy_foo_obj(foo_obj); +foo_error: + return -EINVAL; +} + +static void __exit example_exit(void) +{ + destroy_foo_obj(baz_obj); + destroy_foo_obj(bar_obj); + destroy_foo_obj(foo_obj); + kset_unregister(example_kset); +} + +module_init(example_init); +module_exit(example_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Greg Kroah-Hartman ");