Blame view
samples/kfifo/record-example.c
3.98 KB
5bf2b1932 kfifo: add exampl... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
/* * Sample dynamic sized record fifo implementation * * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net> * * Released under the GPL version 2 only. * */ #include <linux/init.h> #include <linux/module.h> #include <linux/proc_fs.h> #include <linux/mutex.h> #include <linux/kfifo.h> /* * This module shows how to create a variable sized record fifo. */ /* fifo size in elements (bytes) */ #define FIFO_SIZE 128 /* name of the proc entry */ #define PROC_FIFO "record-fifo" /* lock for procfs read access */ static DEFINE_MUTEX(read_lock); /* lock for procfs write access */ static DEFINE_MUTEX(write_lock); /* * define DYNAMIC in this example for a dynamically allocated fifo. * * Otherwise the fifo storage will be a part of the fifo structure. */ #if 0 #define DYNAMIC #endif /* * struct kfifo_rec_ptr_1 and STRUCT_KFIFO_REC_1 can handle records of a * length between 0 and 255 bytes. * * struct kfifo_rec_ptr_2 and STRUCT_KFIFO_REC_2 can handle records of a * length between 0 and 65535 bytes. */ #ifdef DYNAMIC struct kfifo_rec_ptr_1 test; #else typedef STRUCT_KFIFO_REC_1(FIFO_SIZE) mytest; static mytest test; #endif |
a25effa4d kfifo: add explic... |
57 58 59 60 61 62 63 64 65 66 67 68 |
static const char *expected_result[] = { "a", "bb", "ccc", "dddd", "eeeee", "ffffff", "ggggggg", "hhhhhhhh", "iiiiiiiii", "jjjjjjjjjj", }; |
5bf2b1932 kfifo: add exampl... |
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
static int __init testfunc(void) { char buf[100]; unsigned int i; unsigned int ret; struct { unsigned char buf[6]; } hello = { "hello" }; printk(KERN_INFO "record fifo test start "); kfifo_in(&test, &hello, sizeof(hello)); /* show the size of the next record in the fifo */ printk(KERN_INFO "fifo peek len: %u ", kfifo_peek_len(&test)); /* put in variable length data */ for (i = 0; i < 10; i++) { memset(buf, 'a' + i, i + 1); kfifo_in(&test, buf, i + 1); } |
a25effa4d kfifo: add explic... |
90 91 92 93 |
/* skip first element of the fifo */ printk(KERN_INFO "skip 1st element "); kfifo_skip(&test); |
5bf2b1932 kfifo: add exampl... |
94 95 96 97 98 99 100 101 |
printk(KERN_INFO "fifo len: %u ", kfifo_len(&test)); /* show the first record without removing from the fifo */ ret = kfifo_out_peek(&test, buf, sizeof(buf)); if (ret) printk(KERN_INFO "%.*s ", ret, buf); |
a25effa4d kfifo: add explic... |
102 103 |
/* check the correctness of all values in the fifo */ i = 0; |
5bf2b1932 kfifo: add exampl... |
104 105 |
while (!kfifo_is_empty(&test)) { ret = kfifo_out(&test, buf, sizeof(buf)); |
a25effa4d kfifo: add explic... |
106 107 108 109 110 111 112 113 114 115 116 117 118 |
buf[ret] = '\0'; printk(KERN_INFO "item = %.*s ", ret, buf); if (strcmp(buf, expected_result[i++])) { printk(KERN_WARNING "value mismatch: test failed "); return -EIO; } } if (i != ARRAY_SIZE(expected_result)) { printk(KERN_WARNING "size mismatch: test failed "); return -EIO; |
5bf2b1932 kfifo: add exampl... |
119 |
} |
a25effa4d kfifo: add explic... |
120 121 |
printk(KERN_INFO "test passed "); |
5bf2b1932 kfifo: add exampl... |
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
return 0; } static ssize_t fifo_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { int ret; unsigned int copied; if (mutex_lock_interruptible(&write_lock)) return -ERESTARTSYS; ret = kfifo_from_user(&test, buf, count, &copied); mutex_unlock(&write_lock); return ret ? ret : copied; } static ssize_t fifo_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int ret; unsigned int copied; if (mutex_lock_interruptible(&read_lock)) return -ERESTARTSYS; ret = kfifo_to_user(&test, buf, count, &copied); mutex_unlock(&read_lock); return ret ? ret : copied; } static const struct file_operations fifo_fops = { .owner = THIS_MODULE, .read = fifo_read, .write = fifo_write, |
6038f373a llseek: automatic... |
162 |
.llseek = noop_llseek, |
5bf2b1932 kfifo: add exampl... |
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
}; static int __init example_init(void) { #ifdef DYNAMIC int ret; ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL); if (ret) { printk(KERN_ERR "error kfifo_alloc "); return ret; } #else INIT_KFIFO(test); #endif |
a25effa4d kfifo: add explic... |
179 180 181 182 183 184 |
if (testfunc() < 0) { #ifdef DYNAMIC kfifo_free(&test); #endif return -EIO; } |
5bf2b1932 kfifo: add exampl... |
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) { #ifdef DYNAMIC kfifo_free(&test); #endif return -ENOMEM; } return 0; } static void __exit example_exit(void) { remove_proc_entry(PROC_FIFO, NULL); #ifdef DYNAMIC kfifo_free(&test); #endif } module_init(example_init); module_exit(example_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>"); |