1实验一Linux内核通用链表的使用一、实验目的学习Linux内核通用链表的设计原理,熟练掌握Linux内核通用链表的使用。二、实验内容1、掌握Linux通用链表的创建2、掌握通用链表添加元素、删除元素和遍历链表的方法3、掌握通用链表的查找方法三、实现原理Linux的内核源文件list.h提供了所有的链表定义,以及各类链表的操作接口和实现。其中创建链表的方法如下:LIST_HEAD(my_list);在指定的head后插入新节点,常用于堆栈数据结构的实现list_add(structlist_head*new,structlist_head*head);在指定的head前插入新节点,常用于队列数据结构的实现list_add_tail(structlist_head*new,structlist_head*head);从链表中删除一个指定节点list_del(structlist_head*entry);根据当前链表节点指针ptr获得宿主节点指针list_entry(ptr,type,member);遍历链表list_for_each(pos,head);四、实现代码和运行结果#includestdio.h#includemalloc.h#includelist.hstructuser{intid;structlist_headlist;};intmain(void){structuser*p;LIST_HEAD(user_queue);for(inti=0;i10;i++){p=(structuser*)malloc(sizeof(structuser));p-id=i;list_add_tail(&p-list,&user_queue);}structlist_head*q;list_for_each(q,&user_queue){p=list_entry(q,structuser,list);2printf(%d\n,p-id);}return0;}#includestdio.h#includemalloc.h#includelist.hstructuser{charusername[20];intid;structlist_headlist;};intmain(void){structuser*p;LIST_HEAD(head);for(inti;i10;i++){p=(structuser*)malloc(sizeof(structuser));p-id=i+1;printf(user%2d,Pleaseinputusername:,i+1);scanf(%s,p-username);list_add_tail(&(p-list),&head);}structlist_head*tmp;list_for_each(tmp,&head){p=list_entry(tmp,structuser,list);printf(%d\t%s\n,p-id,p-username);3}list_for_each(tmp,&head){p=list_entry(tmp,structuser,list);if(p-id==5)printf(%s\n,p-username);}return0;}实验二Linux内核通用哈希链表的使用一、实验目的学习Linux内核通用哈希链表的设计原理,熟练掌握Linux内核通用哈希链表的使用。二、实验内容1、掌握Linux通用哈希链表的创建。2、掌握通用哈希链表添加元素、查找元素的方法。三、实现原理Linux的内核源文件list.h提供了哈希链表的各种操作接口和实现。其中创建具有16个元素的哈希链表的方法如下:structhlist_headuser_hash[16];在上述user_hash数组的16个元素中存放的哈希表头元素定义如下:structhlist_head{structhlist_node*first;};哈希链表节点元素定义如下:structhlist_node{structhlist_node*next,**pprev;};4本实验对哈希链表宿主节点的name值进行散列的算法如下:unsignedintBKDRHash(unsignedchar*str);{unsignedintseed=131;unsignedinthash=0;while(*str){hash=hash*seed+(*str++);}return(hash&0x7FFFFFFF);}于是,本实验对一个字符串name求最终哈希值hash的方法如下:unsignedinthash=BKDRHash(name)&15;内核源文件list.h定义了以下若干接口,用于对哈希链表进行各种操作:在指定的哈希链表头h所指向的链表头插入新节点hlist_add_head(structhlist_node*n,structhlist_head*h);根据当前哈希链表节点指针ptr获得好像链表宿主节点指针hlist_entry(ptr,type,member);遍历哈希链表中某个key值所对应的链表hlist_for_each_entry(tpos,pos,head,member);四、实现代码和运行结果#includestdio.h#includestring.h#includelist.hstructusermap{structhlist_nodehlist;unsignedcharname[8];};voidhlist_print(structhlist_head*hl_head);unsignedintBKDRHash(unsignedchar*str);unsignedcharhash_add(structhlist_node*hl_node,structhlist_head*hl_head);intmain(void){structhlist_headuser_hash[16];for(inti=0;i16;i++)INIT_HLIST_HEAD(&user_hash[i]);structusermapuser[3];strcpy(user[0].name,smith);strcpy(user[1].name,john);strcpy(user[2].name,bob);for(inti=0;i3;i++)hlist_add_head(&(user[i].hlist),&user_hash[BKDRHash(user[i].name)&15]);hlist_print(user_hash);structusermapnew_user[2];strcpy(new_user[0].name,john);5strcpy(new_user[1].name,lisa);for(inti=0;i2;i++)if(!hash_add(&(new_user[i].hlist),&user_hash[BKDRHash(new_user[i].name)&15]))printf(用户%s重复,添加失败!\n,new_user[i].name);hlist_print(user_hash);return0;}voidhlist_print(structhlist_head*hl_head){structusermap*puser;structhlist_node*phnode;for(inti=0;i16;i++){printf(%d\t,i);hlist_for_each_entry(puser,phnode,&hl_head[i],hlist)printf(%s\t,puser-name);printf(\n);}}unsignedintBKDRHash(unsignedchar*str){unsignedintseed=131;unsignedinthash=0;while(*str){hash=hash*seed+(*str++);}return(hash&0x7FFFFFFF);}unsignedcharhash_add(structhlist_node*hl_node,structhlist_head*hl_head){char*name=hlist_entry(hl_node,structusermap,hlist)-name;structusermap*puser;structhlist_node*pnode;hlist_for_each_entry(puser,pnode,hl_head,hlist){if(!strcmp(puser-name,name))return0;}hlist_add_head(hl_node,hl_head);return1;}6实验三Linux多线程程序设计一、实验目的学习Linux下多线程程序的编写,掌握IP报文分段重组模拟程序的整体框架。二、实验内容完成Linux下多线程的程序编写,利用线程同步的方法,完成多线程访问一个由Linux内核通用链表所实现的消息队列。三、实现原理线程模型本实验要求创建两个线程,分别为由main函数代表的线程1和由run函数代表的线程2。其中线程1模拟从网络持续接收消息,并将收到的消息放入消息队列中;线程2模拟网络协议处理程序,当消息队列不空时,持续从消息队列头取出下一个收到的消息7并进行处理,如下图所示:线程互斥与同步方法由于消息队列是一临界资源,线程1和线程2将竞争访问该队列,因此必须对线程1和线程2进行互斥与同步管理。即当线程1正在向消息队列尾放入消息时,线程2必须等待线程1操作完毕并退出对临界资源的操作后,方可以从该队列头部中取出下一个消息进行处理,反之亦然。此外,当消息队列为空时,线程2将进入休眠状态,当消息队列不空时,线程2被线程1唤醒后继续处理。下面给出实现线程1和线程2互斥与同步的部分关键代码。pthread_mutex_tmqlock=PTHREAD_MUTEX_INITIALIZER;pthread_cond_tmqlock_ready=PTHREAD_COND_INITIALIZER;intmain(){structmsg_buff*msg;for(;;){...pthread_mutex_lock(&mqlock);/*加锁互斥量*/list_add_tail(msg-list,&msg_queue));/*消息入队列尾*/pthread_mutex_unlock(&mqlock);/*解锁互斥量*/pthread_cond_signal(&mqlock_ready);...}...return0;}void*run(void*arg){structmsg_buff*msg;for(;;){pthread_mutex_lock(&mqlock);while(list_empty(&msg_queue))pthread_cond_wait(&mqlock_ready,&mqlock);msg=getnextmsg(msg_queue.next);pthread_mutex_unlock(&mqlock);handle_msg(msg);}}消息队列mutex线程1线程28四、实现代码和运行结果#includestdio.h#includestdlib.h#includeunistd.h#includepthread.h#includelist.h#definePAUSE3000void*run(void*);/*消息处理线程*/voidadd_msg(int);structmsg_buff*getnextmsg(structlist_head*);voidhandle_msg(structmsg_buff*);structmsg_buff{intid;structlist_headlist;}pthread_mutex_tmqlock=PTHREAD_M