├── README.md ├── color ├── logger.py └── print-color.sh ├── ftrace ├── ftrace-func.sh └── ftrace-graph.sh ├── ioctl ├── Makefile ├── ioctl-dev.c ├── ioctl-dev.h └── test.c ├── kmod ├── args │ ├── Makefile │ └── args.c └── hello │ ├── Makefile │ └── hello.c ├── perf ├── flamegraph.sh └── main.c └── strace ├── bar ├── foo.c └── strace-lsof.sh /README.md: -------------------------------------------------------------------------------- 1 | # ipads-tutorial07 2 | 3 | Slides: https://docs.google.com/presentation/d/1ro92kZM_cjy47iJg68elo7vx9oZCv_TSg5zr1eT3NZ8/edit?usp=sharing 4 | -------------------------------------------------------------------------------- /color/logger.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import sys 3 | 4 | class CustomFormatter(logging.Formatter): 5 | """Logging Formatter to add colors and count warning / errors""" 6 | 7 | grey = "\x1b[38;21m" 8 | yellow = "\x1b[33;21m" 9 | red = "\x1b[31;21m" 10 | bold_red = "\x1b[31;1m" 11 | reset = "\x1b[0m" 12 | format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" 13 | 14 | FORMATS = { 15 | logging.DEBUG: grey + format + reset, 16 | logging.INFO: grey + format + reset, 17 | logging.WARNING: yellow + format + reset, 18 | logging.ERROR: red + format + reset, 19 | logging.CRITICAL: bold_red + format + reset 20 | } 21 | 22 | def format(self, record): 23 | log_fmt = self.FORMATS.get(record.levelno) 24 | formatter = logging.Formatter(log_fmt) 25 | return formatter.format(record) 26 | 27 | # create logger with 'spam_application' 28 | logger = logging.getLogger("Sample") 29 | 30 | # create console handler with a higher log level 31 | ch = logging.StreamHandler() 32 | ch.setLevel(logging.DEBUG) 33 | 34 | if len(sys.argv)> 1: 35 | if sys.argv[1] == 'log': 36 | ch.setFormatter(logging.Formatter('%(asctime)s : %(levelname)s : %(name)s : %(message)s')) 37 | elif sys.argv[1] == 'color': 38 | ch.setFormatter(CustomFormatter()) 39 | 40 | if len(sys.argv) > 2: 41 | logger.setLevel(logging.__getattribute__(sys.argv[2])) 42 | else: 43 | logger.setLevel(logging.DEBUG) 44 | 45 | logger.addHandler(ch) 46 | 47 | # logger.debug("debug message") 48 | # logger.info("info message") 49 | # logger.warning("warning message") 50 | # logger.error("error message") 51 | # logger.critical("critical message") 52 | 53 | import random 54 | import time 55 | for _ in range(100): 56 | i = random.randint(0, 10) 57 | if i <= 4: 58 | logger.info("Value is {} - Everything is fine".format(i)) 59 | elif i <= 6: 60 | logger.warning("Value is {} - System is getting hot".format(i)) 61 | elif i <= 8: 62 | logger.error("Value is {} - Dangerous region".format(i)) 63 | else: 64 | logger.critical("Maximum value reached") 65 | time.sleep(0.3) 66 | 67 | -------------------------------------------------------------------------------- /color/print-color.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | RED="\e[31m" 4 | GREEN="\e[32m" 5 | ENDCOLOR="\e[0m" 6 | 7 | echo -e "${RED}This is some red text, ${ENDCOLOR}" 8 | echo -e "${GREEN}And this is some green text${ENDCOLOR}" 9 | 10 | for R in $(seq 0 20 255); do 11 | for G in $(seq 0 20 255); do 12 | for B in $(seq 0 20 255); do 13 | printf "\e[38;2;${R};${G};${B}m█\e[0m"; 14 | done 15 | done 16 | done 17 | -------------------------------------------------------------------------------- /ftrace/ftrace-func.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | dir=/sys/kernel/debug/tracing 4 | 5 | sysctl kernel.ftrace_enabled=1 6 | 7 | echo function > ${dir}/current_tracer 8 | 9 | echo 1 > ${dir}/tracing_on 10 | 11 | $@ 12 | 13 | echo 0 > ${dir}/tracing_on 14 | 15 | less ${dir}/trace 16 | -------------------------------------------------------------------------------- /ftrace/ftrace-graph.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | dir=/sys/kernel/debug/tracing 4 | 5 | sysctl kernel.ftrace_enabled=1 6 | 7 | echo function_graph > ${dir}/current_tracer 8 | 9 | echo 1 > ${dir}/tracing_on 10 | 11 | $@ 12 | 13 | echo 0 > ${dir}/tracing_on 14 | 15 | less ${dir}/trace 16 | -------------------------------------------------------------------------------- /ioctl/Makefile: -------------------------------------------------------------------------------- 1 | obj-m += ioctl-dev.o 2 | 3 | all: 4 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 5 | 6 | clean: 7 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 8 | -------------------------------------------------------------------------------- /ioctl/ioctl-dev.c: -------------------------------------------------------------------------------- 1 | #include /* Needed by all modules */ 2 | #include /* Needed for KERN_INFO */ 3 | #include /* Needed for the macros */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "ioctl-dev.h" 10 | 11 | static volatile unsigned long *shared_mem = NULL; 12 | 13 | static int tutorial_dev_mmap(struct file *file, struct vm_area_struct *vma) 14 | { 15 | size_t size = vma->vm_end - vma->vm_start; 16 | void *mem = NULL; 17 | 18 | if (vma->vm_pgoff != 0) 19 | return -EINVAL; 20 | 21 | if (!(mem = kmalloc(size, GFP_KERNEL))) 22 | return -ENOMEM; 23 | memset(mem, 0, size); 24 | 25 | if (remap_pfn_range(vma, vma->vm_start, virt_to_phys(mem) >> PAGE_SHIFT, 26 | size, vma->vm_page_prot)) { 27 | kfree(mem); 28 | return -EAGAIN; 29 | } 30 | shared_mem = mem; 31 | 32 | return 0; 33 | } 34 | 35 | static long tutorial_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 36 | { 37 | switch (cmd) { 38 | case TUTORIAL_TEST_PRINT: { 39 | pr_info("%s:%d shared_mem = %px, %lx\n", __func__, __LINE__, 40 | shared_mem, shared_mem ? shared_mem[0] : 0xdead); 41 | break; 42 | } 43 | default: 44 | break; 45 | } 46 | return 0; 47 | } 48 | 49 | static int tutorial_dev_open(struct inode *inode, struct file *filep) { 50 | pr_info("%s:%d hello shared_mem: %px\n", __func__, __LINE__, shared_mem); 51 | return 0; 52 | } 53 | 54 | static int tutorial_dev_release(struct inode *inode, struct file *filep) { 55 | pr_info("%s:%d bye shared_mem: %px\n", __func__, __LINE__, shared_mem); 56 | shared_mem = NULL; 57 | return 0; 58 | } 59 | 60 | static const struct file_operations tutorial_fops = { 61 | .owner = THIS_MODULE, 62 | .read = NULL, 63 | .write = NULL, 64 | .mmap = tutorial_dev_mmap, 65 | .unlocked_ioctl = tutorial_dev_ioctl, 66 | .open = tutorial_dev_open, 67 | .release = tutorial_dev_release, 68 | }; 69 | 70 | static struct miscdevice tutorial_dev = { 71 | .minor = MISC_DYNAMIC_MINOR, 72 | .name = "tutorial_dev", 73 | .fops = &tutorial_fops, 74 | }; 75 | 76 | static int __init ioctl_dev_init(void) 77 | { 78 | int err; 79 | 80 | err = misc_register(&tutorial_dev); 81 | if (err != 0) { 82 | pr_err("%s:%d ERROR: %d\n", __func__, __LINE__, err); 83 | return err; 84 | } 85 | pr_info("%s:%d tutorial_dev installed\n", __func__, __LINE__); 86 | return 0; 87 | } 88 | 89 | static void __exit ioctl_dev_exit(void) 90 | { 91 | misc_deregister(&tutorial_dev); 92 | } 93 | 94 | module_init(ioctl_dev_init); 95 | module_exit(ioctl_dev_exit); 96 | 97 | MODULE_LICENSE("GPL"); 98 | -------------------------------------------------------------------------------- /ioctl/ioctl-dev.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define TUTORIAL_MAGIC 'k' 7 | #define TUTORIAL_TEST_PRINT _IO(TUTORIAL_MAGIC, 1) 8 | -------------------------------------------------------------------------------- /ioctl/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "ioctl-dev.h" 11 | 12 | #define TUTORIAL_DEV_NAME "/dev/tutorial_dev" 13 | 14 | int main(void) { 15 | int size = 4 << 20; 16 | int fd = open(TUTORIAL_DEV_NAME, O_RDWR); 17 | if (fd < 0) { 18 | fprintf(stderr, "Failed to open %s\n", TUTORIAL_DEV_NAME); 19 | return -1; 20 | } 21 | 22 | ioctl(fd, TUTORIAL_TEST_PRINT, NULL); 23 | 24 | unsigned long *mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 25 | if (mem == MAP_FAILED) { 26 | perror("MAP_FAILED"); 27 | return -1; 28 | } 29 | 30 | mem[0] = 0x1234; 31 | 32 | ioctl(fd, TUTORIAL_TEST_PRINT, NULL); 33 | 34 | munmap(mem, size); 35 | close(fd); 36 | printf("Bye\n"); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /kmod/args/Makefile: -------------------------------------------------------------------------------- 1 | obj-m += args.o 2 | 3 | all: 4 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 5 | 6 | clean: 7 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 8 | -------------------------------------------------------------------------------- /kmod/args/args.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hello-5.c - Demonstrates command line argument passing to a module. 3 | */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | MODULE_LICENSE("GPL"); 11 | MODULE_AUTHOR("Mark Lee"); 12 | 13 | static short int myshort = 1; 14 | static int myint = 420; 15 | static long int mylong = 9999; 16 | static char *mystring = "blah"; 17 | static int myintArray[2] = { -1, -1 }; 18 | static int arr_argc = 0; 19 | 20 | /* 21 | * module_param(foo, int, 0000) 22 | * The first param is the parameters name 23 | * The second param is it's data type 24 | * The final argument is the permissions bits, 25 | * for exposing parameters in sysfs (if non-zero) at a later stage. 26 | */ 27 | 28 | module_param(myshort, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 29 | MODULE_PARM_DESC(myshort, "A short integer"); 30 | module_param(myint, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 31 | MODULE_PARM_DESC(myint, "An integer"); 32 | module_param(mylong, long, S_IRUSR); 33 | MODULE_PARM_DESC(mylong, "A long integer"); 34 | module_param(mystring, charp, 0000); 35 | MODULE_PARM_DESC(mystring, "A character string"); 36 | 37 | /* 38 | * module_param_array(name, type, num, perm); 39 | * The first param is the parameter's (in this case the array's) name 40 | * The second param is the data type of the elements of the array 41 | * The third argument is a pointer to the variable that will store the number 42 | * of elements of the array initialized by the user at module loading time 43 | * The fourth argument is the permission bits 44 | */ 45 | module_param_array(myintArray, int, &arr_argc, 0000); 46 | MODULE_PARM_DESC(myintArray, "An array of integers"); 47 | 48 | static int __init kmod_args_init(void) 49 | { 50 | int i; 51 | printk(KERN_INFO "Hello, world 5\n=============\n"); 52 | printk(KERN_INFO "myshort is a short integer: %hd\n", myshort); 53 | printk(KERN_INFO "myint is an integer: %d\n", myint); 54 | printk(KERN_INFO "mylong is a long integer: %ld\n", mylong); 55 | printk(KERN_INFO "mystring is a string: %s\n", mystring); 56 | for (i = 0; i < (sizeof myintArray / sizeof (int)); i++) 57 | { 58 | printk(KERN_INFO "myintArray[%d] = %d\n", i, myintArray[i]); 59 | } 60 | printk(KERN_INFO "got %d arguments for myintArray.\n", arr_argc); 61 | return 0; 62 | } 63 | 64 | static void __exit kmod_args_exit(void) 65 | { 66 | printk(KERN_INFO "Goodbye, world 5\n"); 67 | } 68 | 69 | module_init(kmod_args_init); 70 | module_exit(kmod_args_exit); 71 | -------------------------------------------------------------------------------- /kmod/hello/Makefile: -------------------------------------------------------------------------------- 1 | obj-m += hello.o 2 | 3 | all: 4 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 5 | 6 | clean: 7 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 8 | -------------------------------------------------------------------------------- /kmod/hello/hello.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hello-3.c - Illustrating the __init, __initdata and __exit macros. 3 | */ 4 | #include /* Needed by all modules */ 5 | #include /* Needed for KERN_INFO */ 6 | #include /* Needed for the macros */ 7 | 8 | #define DRIVER_AUTHOR "Mark Lee" 9 | #define DRIVER_DESC "A sample driver" 10 | 11 | static int hello3_data __initdata = 3; 12 | 13 | static int __init hello_3_init(void) 14 | { 15 | printk(KERN_INFO "Hello, world %d\n", hello3_data); 16 | return 0; 17 | } 18 | 19 | static void __exit hello_3_exit(void) 20 | { 21 | printk(KERN_INFO "Goodbye, world 3\n"); 22 | } 23 | 24 | module_init(hello_3_init); 25 | module_exit(hello_3_exit); 26 | 27 | 28 | /* 29 | * Get rid of taint message by declaring code as GPL. 30 | */ 31 | MODULE_LICENSE("GPL"); 32 | 33 | /* 34 | * Or with defines, like this: 35 | */ 36 | MODULE_AUTHOR(DRIVER_AUTHOR); /* Who wrote this module? */ 37 | MODULE_DESCRIPTION(DRIVER_DESC); /* What does this module do */ 38 | -------------------------------------------------------------------------------- /perf/flamegraph.sh: -------------------------------------------------------------------------------- 1 | 2 | #step 1 build perf 3 | # cd /path/to/kernel/tools 4 | # make perf 5 | 6 | #step 2 download flamegraph src code 7 | # wget https://github.com/brendangregg/FlameGraph/archive/master.zip 8 | # unzip master.zip 9 | # export PATH=$PATH:/path/to/FlameGraph 10 | 11 | #step 3 generate perf sample file 12 | sudo perf record -F 99 --call-graph lbr -g -o in-fb.data ./a.out 13 | sudo perf script -i in-fb.data > in-fb.perf 14 | 15 | #step 4 generate flamegraph 16 | ./FlameGraph/stackcollapse-perf.pl in-fb.perf > in-fb.folded 17 | ./FlameGraph/flamegraph.pl in-fb.folded >in-fb-cpu.svg 18 | 19 | #step 5 use browser to open flamegraph.svg 20 | 21 | -------------------------------------------------------------------------------- /perf/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void swap(const void* a, const void* b, int size); 6 | void quicksort(void* base, int left, int right, int size, int (*cmp)(const void* a, const void* b)); 7 | int cmp_string(const void* a, const void* b); 8 | int cmp_int(const void* a, const void* b); 9 | 10 | int comp(const void *j, const void *i); 11 | void show_card(int b[], char n[]); 12 | void shuffle(void); 13 | 14 | int main (void) 15 | { 16 | int i = 0; 17 | while(i < 100000){ 18 | shuffle(); 19 | i++; 20 | } 21 | return 0; 22 | } 23 | 24 | void shuffle(void) 25 | { 26 | static char n[] = {'2','3','4','5','6','7','8','9','T','J','Q','K','A'}; 27 | int *a = (int *)malloc(sizeof(int)*53); 28 | int *b1 = (int *)malloc(sizeof(int)*13); 29 | int *b2 = (int *)malloc(sizeof(int)*13); 30 | int *b3 = (int *)malloc(sizeof(int)*13); 31 | int *b4 = (int *)malloc(sizeof(int)*13); 32 | memset(a,0,sizeof(int)*53); 33 | memset(b1,0,sizeof(int)*13); 34 | memset(b2,0,sizeof(int)*13); 35 | memset(b3,0,sizeof(int)*13); 36 | memset(b4,0,sizeof(int)*13); 37 | int b11=0,b22=0,b33=0,b44=0,t=1,m,flag,i; 38 | while(t<52) 39 | { 40 | m=rand()%52; 41 | for(flag=1,i=1;i<=t&&flag;i++) 42 | if(m==a[i]) 43 | flag=0; 44 | 45 | if(flag) 46 | { 47 | a[t++]=m; 48 | if(t%4==0) 49 | b1[b11++]=a[t-1]; 50 | else 51 | if(t%4==1) 52 | b2[b22++]=a[t-1]; 53 | else 54 | if(t%4==2) 55 | b3[b33++]=a[t-1]; 56 | else 57 | if(t%4==3) 58 | b4[b44++]=a[t-1]; 59 | } 60 | } 61 | 62 | /* 63 | qsort(b1, 13, sizeof(int), comp); 64 | qsort(b2, 13, sizeof(int), comp); 65 | qsort(b3, 13, sizeof(int), comp); 66 | qsort(b4, 13, sizeof(int), comp); 67 | */ 68 | quicksort(b1, 0, 12, sizeof(int), cmp_int); 69 | quicksort(b2, 0, 12, sizeof(int), cmp_int); 70 | quicksort(b3, 0, 12, sizeof(int), cmp_int); 71 | quicksort(b4, 0, 12, sizeof(int), cmp_int); 72 | 73 | show_card(b1,n); 74 | show_card(b2,n); 75 | show_card(b3,n); 76 | show_card(b4,n); 77 | } 78 | 79 | void show_card(int b[], char n[]) 80 | { 81 | int i; 82 | printf("\n\006 "); 83 | for(i=0;i<13;i++){ 84 | if(b[i]/13==0) 85 | printf("%c ",n[b[i]%13]); 86 | } 87 | 88 | printf("\n\003 "); 89 | for(i=0;i<13;i++){ 90 | if(b[i]/13==1) 91 | printf("%c ",n[b[i]%13]); 92 | } 93 | 94 | printf("\n\004 "); 95 | for(i=0;i<13;i++){ 96 | if(b[i]/13==2) 97 | printf("%c ",n[b[i]%13]); 98 | } 99 | 100 | printf("\n\005 "); 101 | for(i=0;i<13;i++){ 102 | if(b[i]/13==3 || b[i]/13==4) 103 | printf("%c ",n[b[i]%13]); 104 | } 105 | 106 | printf("\n"); 107 | } 108 | 109 | int comp(const void*j, const void*i) 110 | { 111 | return (*(int*)i-*(int*)j); 112 | } 113 | 114 | void swap(const void* a, const void* b, int size) 115 | { 116 | char tmp = 0; 117 | int i = 0; 118 | while (size > 0) { 119 | tmp = *((char*)a + i); 120 | *((char*)a + i) = *((char*)b + i); 121 | *((char*)b + i) = tmp; 122 | ++i; 123 | --size; 124 | } 125 | } 126 | 127 | void quicksort(void* base, int left, int right, int size, int (*cmp)(const void* a, const void* b)) 128 | { 129 | if (left >= right) return; 130 | char* pleft = (char*)base + left * size; 131 | char* pkey = (char*)base + (left + (right - left) / 2) * size; 132 | swap(pleft, pkey, size); 133 | int last = left; 134 | char* plast = (char*)base + last * size; 135 | for (int i = left + 1; i <= right; ++i) { 136 | char* pi = (char*)base + i * size; 137 | if (cmp(pi, pleft) < 0) { 138 | ++last; 139 | plast = (char*)base + last * size; 140 | swap(pi, plast, size); 141 | } 142 | } 143 | swap(pleft, plast, size); 144 | quicksort(base, left, last - 1, size, cmp); 145 | quicksort(base, last + 1, right, size, cmp); 146 | } 147 | 148 | int cmp_string(const void* a, const void* b) 149 | { 150 | const char** lhs = (const char**)a; 151 | const char** rhs = (const char**)b; 152 | return strcmp(*lhs, *rhs); 153 | } 154 | 155 | int cmp_int(const void* a, const void* b) 156 | { 157 | const int* lhs = (const int*)a; 158 | const int* rhs = (const int*)b; 159 | if (*lhs < *rhs) { 160 | return -1; 161 | } else if (*lhs == *rhs) { 162 | return 0; 163 | } else { 164 | return 1; 165 | } 166 | } 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /strace/bar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/130B848/ipads-tutorial07/cc66ef9e07b0e9fc07379f1a7867562a13e80d55/strace/bar -------------------------------------------------------------------------------- /strace/foo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) { 5 | open("./bar", O_CREAT|O_RDONLY); 6 | sleep(1200); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /strace/strace-lsof.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | strace -o lsof.strace lsof -p $@ 4 | --------------------------------------------------------------------------------