├── Makefile ├── README.md ├── dummydrv.c └── writer.c /Makefile: -------------------------------------------------------------------------------- 1 | DRIVER_NAME = dummydrv 2 | obj-m := $(DRIVER_NAME).o 3 | 4 | all: kernel_module writer 5 | 6 | kernel_module: $(DRIVER_NAME).c 7 | make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules 8 | 9 | writer: writer.c 10 | $(CC) -Wall -o writer writer.c -lrt 11 | 12 | clean: 13 | make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean 14 | rm -f writer 15 | 16 | check: all 17 | lsmod | grep dummydrv || $(MAKE) install_driver 18 | sudo ./writer 19 | 20 | install_driver: $(DRIVER_BIN) 21 | sudo insmod $(DRIVER_NAME).ko 22 | sudo mknod /dev/$(DRIVER_NAME) c 240 0 23 | 24 | uninstall_driver: 25 | sudo rmmod $(DRIVER_NAME) 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Test the system calls to copy data between kernel and user space 2 | 3 | Please install kernel headers first: 4 | ```shell 5 | sudo apt-get install linux-headers-generic 6 | ``` 7 | 8 | Usage: 9 | ```shell 10 | $ make check 11 | ``` 12 | -------------------------------------------------------------------------------- /dummydrv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define SUCCESS 0 8 | #define DEVICE_NAME "dummydrv" 9 | #define BUF_LEN 2981 /* Max length of the message from the device */ 10 | 11 | 12 | static int major_num = 240; /* major_num number assigned to our device driver */ 13 | static int dev_open_count = 0; /* Is device open? Used to prevent multiple */ 14 | 15 | static char msg[BUF_LEN]; /* The msg the device will give when asked */ 16 | 17 | static int device_open(struct inode *inode, struct file *file) 18 | { 19 | if (dev_open_count) 20 | return -EBUSY; 21 | 22 | dev_open_count++; 23 | printk("<1>device_open call\n"); 24 | return SUCCESS; 25 | } 26 | 27 | static int device_release(struct inode *inode, struct file *file) 28 | { 29 | dev_open_count--; /* We're now ready for our next caller */ 30 | printk("<1>device_release call\n"); 31 | return 0; 32 | } 33 | 34 | static ssize_t device_read(struct file *filp, 35 | char *buffer, /* The buffer to fill with data */ 36 | size_t length, /* The length of the buffer */ 37 | loff_t *offset) /* Our offset in the file */ 38 | { 39 | if (length < BUF_LEN) { 40 | copy_to_user(buffer, msg, length); 41 | return length; 42 | } 43 | else { 44 | copy_to_user(buffer, msg, BUF_LEN); 45 | return BUF_LEN; 46 | } 47 | } 48 | 49 | static ssize_t device_write(struct file *filp, 50 | const char *buff, 51 | size_t len, 52 | loff_t *off) 53 | { 54 | if (BUF_LEN >= len) 55 | return len; 56 | else { 57 | printk ("Support maximum length = %d\n", BUF_LEN); 58 | return -EINVAL; 59 | } 60 | } 61 | 62 | static struct file_operations fops = { 63 | .read = device_read, 64 | .write = device_write, 65 | .open = device_open, 66 | .release = device_release 67 | }; 68 | 69 | static int __init dummydrv_init(void) 70 | { 71 | int ret = register_chrdev(major_num, DEVICE_NAME, &fops); 72 | 73 | if (ret < 0) { 74 | printk("Registering the character device failed with %d\n", ret); 75 | return ret; 76 | } 77 | 78 | printk("'create driver file: mknod /dev/%s c %d 0'.\n", DEVICE_NAME, major_num); 79 | memset(msg, 0x0, 80); 80 | return 0; 81 | } 82 | 83 | static void __exit dummydrv_exit(void) 84 | { 85 | unregister_chrdev(major_num, DEVICE_NAME); 86 | } 87 | 88 | module_init(dummydrv_init); 89 | module_exit(dummydrv_exit); 90 | -------------------------------------------------------------------------------- /writer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define BUF_LEN 4 11 | #define TIMES 300 12 | 13 | static char *dev_name = "/dev/dummydrv"; 14 | 15 | static uint64_t time_in_ns() 16 | { 17 | struct timespec tp; 18 | clock_gettime(CLOCK_MONOTONIC, &tp); 19 | return (uint64_t) tp.tv_sec * (1000ULL * 1000ULL * 1000ULL) + 20 | tp.tv_nsec; 21 | } 22 | 23 | int main(int argc,char *argv[]) 24 | { 25 | int fd; 26 | int i; 27 | int nwrite; 28 | uint64_t start, end, use; 29 | 30 | fd = open(dev_name, O_RDWR); 31 | if (fd == -1) { 32 | printf("open failed.\n"); 33 | return EXIT_FAILURE; 34 | } 35 | 36 | char *buf = (char *) malloc(BUF_LEN); 37 | if (NULL == buf) { 38 | printf("malloc error\n"); 39 | return EXIT_FAILURE; 40 | } 41 | 42 | start = time_in_ns(); 43 | 44 | for (i=0; i < TIMES; i++) { 45 | nwrite = write(fd, (const void *) buf, BUF_LEN); 46 | if (nwrite != BUF_LEN) { 47 | printf ("write buf to driver failed,return val:%d \n", nwrite); 48 | return nwrite; 49 | } 50 | } 51 | 52 | end = time_in_ns(); 53 | 54 | use = end - start; 55 | printf("each time write to kernel takes time:%3llu.%09llus\n", 56 | (unsigned long long) use / 1000000000, 57 | (unsigned long long) use % 1000000000); 58 | 59 | close(fd); 60 | 61 | return EXIT_SUCCESS; 62 | } 63 | --------------------------------------------------------------------------------