- 论坛徽章:
- 0
|
本帖最后由 nuclearxin 于 2017-03-31 14:31 编辑
- linux-mkov:~/jerry # cat hh.c
- #include <linux/module.h>
- #include <linux/mm.h>
- #include <linux/gfp.h>
- #include <linux/kernel.h>
- #include <linux/proc_fs.h>
- #include <asm/uaccess.h>
- #include <linux/slab.h>
- #include <linux/string.h>
- struct cir_list {
- unsigned int num ;
- struct list_head * cir_entry ;
- struct list_head * write;
- struct list_head * read;
- };
- struct cir_node {
- struct list_head list;
- int w_off_set ;
- int r_off_set ;
- char * buff ;
- int ok ;
- };
- struct cir_list * jerry;
- int add_node (struct cir_list *c, struct cir_node * n)
- {
- if(c == NULL) return 0;
- if(n == NULL) return 0;
- if(c->cir_entry == NULL){
- c->cir_entry = &n->list;
- c->write = &n->list;
- c->read = &n->list;
- printk("create the first node\n");
- return 1;
- }else {
- printk("add the new node to the list\n");
- list_add(&n->list,c->cir_entry);
- c->num +=1;
- printk("the num of c %d \n", c->num);
- return 1;
- }
- }
- struct cir_list * gen_cir(int n){
- struct cir_list * hello_list;
- hello_list = kmalloc(sizeof(struct cir_list),GFP_KERNEL);
- if(hello_list == NULL){
- return NULL;
- }
- //init the list
- hello_list->cir_entry = NULL;
- hello_list->write = NULL;
- hello_list->num = 0;
- hello_list->read = NULL;
- struct cir_node * hello_node;
- int i;
-
- printk("start to generate nodes in total %d \n",n);
- for(i=0;i<n;i++){
- printk("start to generate %d \n",i);
- hello_node = kmalloc(sizeof(struct cir_node),GFP_KERNEL);
- if(hello_node == NULL) {
- printk("not enough mem\n");
- //TO DO #free all the node already allocated;
- return NULL;
- }
- //init the node
- hello_node->list.next = &hello_node->list;
- hello_node->list.prev = &hello_node->list;
- hello_node->w_off_set = 0;
- hello_node->r_off_set = 0;
- hello_node->buff = get_zeroed_page(GFP_KERNEL);
- hello_node->ok = 1;
- printk("start to generate %d add_node func\n",i);
- add_node(hello_list,hello_node);
- }
- return hello_list;
- }
- void clean_list_node(struct cir_list * c)
- {
- struct cir_node * n;
- struct list_head * l;
- printk("start to free\n");
- list_for_each(l,c->cir_entry) {
- printk("in for each loop free\n");
- n = list_entry(l, struct cir_node, list);
- if(n==NULL) return;
- free_page(n->buff);
- printk("in for each loop free free_page\n");
- kfree(n);
- printk("in for each loop free node\n");
- }
- printk("out for each loop free list\n");
- //free the head
- printk("free the head \n");
- n = list_entry(c->cir_entry, struct cir_node, list);
- free_page(n->buff);
- printk("head free_page\n");
- kfree(n);
- printk("head node\n");
- kfree(c);
- printk("free the list descriptor\n");
- }
- void write_end(char * buff ,size_t count ,struct cir_list * l )
- {
- printk("----------------------------------start write--------------------------------\n" );
- unsigned int done=0;
- unsigned int left_sp_node;
- struct cir_node * t_node;
- t_node = list_entry(l->write,struct cir_node,list);
- left_sp_node = 4096 - t_node->w_off_set;
- printk("the left space : %d , woffset : %d\n",left_sp_node,t_node->w_off_set );
-
- while(count > left_sp_node){
-
- printk("----------------------------------loops--------------------------------\n" );
- printk(" value lengh %d is bigger than left space %d\n",count,left_sp_node);
- copy_from_user(t_node->buff + t_node->w_off_set,buff+done,left_sp_node);
- printk(" count %d is decrease space\n",count,left_sp_node);
- count -= left_sp_node;
- t_node->w_off_set += left_sp_node;
- done += left_sp_node;
- t_node = list_entry(t_node->list.next,struct cir_node,list);
- t_node->r_off_set = 0;
- t_node->w_off_set = 0;
- left_sp_node = 4096 - t_node->w_off_set;
- printk("----------------------------------loope--------------------------------\n" );
-
- }
-
- printk(" value length %d is small than left space %d\n",count,left_sp_node);
- printk(" --start to append value %d at offset %d---\n",count,t_node->w_off_set );
- copy_from_user(t_node->buff + t_node->w_off_set,buff+done,count);
- t_node->w_off_set += count;
- done += count;
- printk(" finshed append %d , all done is %d in this time\n",count,done);
- l->write = &t_node->list;
- printk("----------------------------------end--------------------------------\n" );
- return 1;
-
- }
- int read_to_write (struct cir_list * l,char * buff,size_t count)
- {
-
- struct cir_node * t_node;
- int o_left;
- t_node = list_entry(l->read,struct cir_node,list);
-
- if(l->read != l->write){
- printk("cross read\n");
- o_left = 4096 - t_node->r_off_set;
- printk("cross read this node have left %d , the request count is %d \n",o_left,count);
- printk("cross area read woffset : %d , roffset : %d \n",t_node->w_off_set,t_node->r_off_set);
- if(count <= o_left){
- printk("cross read count is <= o_left \n");
- copy_to_user(buff,t_node->buff + t_node->r_off_set,count);
- printk("cross area read copy to user %d \n",count);
- t_node->r_off_set += count;
- return count;
- }else{
- copy_to_user(buff ,t_node->buff + t_node->r_off_set,o_left);
- t_node->r_off_set = 4096;
- t_node = list_entry(t_node->list.next,struct cir_node,list);
- l->read = &t_node->list;
- return o_left;
- }
- } else {
- printk("same area read\n");
- o_left = t_node->w_off_set - t_node->r_off_set;
- printk("same area read woffset : %d , roffset : %d \n",t_node->w_off_set,t_node->r_off_set);
- if(o_left==0) return 0;
- if(count <= o_left){
- copy_to_user(buff,t_node->buff + t_node->r_off_set,count);
- t_node->r_off_set += count;
- return count;
- }else{
- copy_to_user(buff ,t_node->buff + t_node->r_off_set,o_left);
- t_node->r_off_set += o_left;
- return o_left;
- }
-
- }
-
- }
- int read_proc(struct file *filp,char *buf,size_t count,loff_t *offp)
- {
- printk("read\n");
- int real_count;
- real_count = read_to_write(jerry,buf,count);
- return real_count;
- }
- int write_proc(struct file *filp,const char *buf,size_t count,loff_t *offp)
- {
- printk("write\n");
- write_end(buf,count,jerry);
- return count;
- }
- struct file_operations proc_fops = {
- read: read_proc,
- write: write_proc
- };
- void create_new_proc_entry()
- {
- proc_create("hello",0,NULL,&proc_fops);
- }
- int proc_init (void) {
-
- jerry = gen_cir(4);
- create_new_proc_entry();
- return 0;
- }
- void proc_cleanup(void) {
- remove_proc_entry("hello",NULL);
- clean_list_node(jerry);
- }
- MODULE_LICENSE("GPL");
- module_init(proc_init);
- module_exit(proc_cleanup);
复制代码 |
|