北京联合大学信息学院实验报告题目:操作系统实验系别:计算机科学与技术专业:计算机科学与技术班级:计算机1303B学号:2013080332058姓名:刘佳敏指导教师:孙悦2015年11月19日实验二进入VI编辑器格式:vi文件名例:visy.cVi编辑器三种工作方式:1.编辑方式:进入VI处于编辑方式2.文本输入方式:在编辑方式下输入a,进入追加方式,输入i,进入插入方式3.命令方式:在输入方式下,按Esc键,由文本输入转向编辑方式,输入冒号:进入命令方式4.退出vi:wq写文件退出:wwenjianming写文件:q!不写退出:wq!写退出编译c文件Gcc-owenjianming.outwenjianming.c运行文件:./wenjianming.out1.实验内容和目的用vi编辑器编辑下列文件,使用gcc编译器和gdb调试器,对下列程序编译运行,分析运行结果。要求至少完成3个程序。2.程序示例(1)/*父子进程之间的同步之例*/#includestdio.hmain(){intpid1;/*声明*/if(pid1=fork())/*调用fork函数复制创建child1进程*/{if(fork())/*调用fork函数复制child1进程创建child2进程,即child1的子进程*/{printf(“parent’scontext.\n”);printf(“parentiswaitingthechild1terminate.\n);wait(0);/*父进程同步等待子进程结束,结束之后进行下一步,否则继续等待*/printf(“parentiswaitingthechild2terminate.\n”);wait(0);/*父进程同步等待子进程结束,结束之后进行下一步,否则继续等待*/printf(“parentterminate.\n”);exit(0);/*父进程终止*/}Else/*如果创建child2进程不成功,进行以下操作*//*child2*/printf(“child2’scontext.\n”);sleep(5);/*休眠5秒钟*/printf(“child2terminate.\n”);exit(0);/*child2进程终止*/}else{if(pid1==0)/*在子进程中*/{printf(“child1’scontext.\n”);sleep(10);/*休眠10秒钟*/printf(“child1terminate.\n”);exit(0);/*child1进程终止*/}}}分析:上述程序是父进程首先创建一个子进程,若成功,再创建另一个子进程,之后三个进程并发执行。究竟谁先执行,是随机的,可根据执行结果判断。试分析该程序的所有运行结果。注释:fork()调用正确完成时,给父进程返回地是被创建子进程的标识,给子进程返回的是0;创建失败时,返回给父进程的时-1;exit(0)进程终止自己wait(0)父进程同步等待子进程结束,即无子进程结束,父进程等待。实验分析:首先fork()正确调用,执行父进程,输出parent’scontextparentiswaitingthechild1terminate.这个时候wait(0);//父进程同步等待子进程结束,即无子进程结束,父进程等待。执行子进程2,输出child2’scontext。然后休眠5秒钟,执行子进程1输出child1’scontext休眠10秒钟。进程2首先结束休眠,输出child2terminate。父进程输出parentiswaitingthechild2terminate。子进程1结束休眠,输出child1terminate,进程1中止自己。父进程child1terminate,中止自己。在运行的时候会发现,在child1’scontext结果出来以后,有一点时间停顿,是因为子进程2还没有结束休眠。同理子进程1也是这样的。(2)管道通信机制通过使用管道实现两个和多个进程之间的通信。所谓管道,就是将一个进程的标准输出与另一个进程的标准输入联系在一起,进行通信的一种方法。同组进程之间可用无名管道进行通信,不同组进程可通过有名管道通信。使用无名管道进行父子进程之间的通信#includesys/types.h#includectype.h#includeunistd.hintpipe(intfiledes[2]);/*创建一个无名管道,filedes[0]为读通道,filedes[1]为写通道*/charparent[]=”amessagetopipe’communication.\n”;/*定义字符串存放于数组中*/main(){intpid,chan1[2];charbuf[100];pipe(chan1);pid=fork();/*创建子进程*/if(pid0)/*如果创建失败*/{printf(“tocreatechilderror\n”);exit(1);/*异常终止*/}if(pid0)/*返回值大于0代表父进程*/{close(chan1[0]);/*父进程关闭读通道*/printf(“parentprocesssendsamessagetochild.\n”);write(chan1[1],parent,sizeof(parent));close(chan1[1]);/*父进程关闭写通道*/printf(“parentprocesswaitsthechildtoterminate.\n”);wait(0);printf(“parentprocessterminates.\n”);}else{close(chan1[1]);/*子进程关闭写通道*/read(chan1[0],buf,100);/*子进程读缓存中的内容*/printf(“themessagereadbychildprocessformparentis%s.\n”,buf);/*输出读的内容*/close(chan1[0]);/*子进程关闭读通道*/printf(“childprocessterminates\n”);}}注释:pipe(intfiledes[2]):创建一个无名管道,filedes[0]为读通道,filedes[1]为写通道。结果分析:首先程序创建了一个无名管道,如果子进程创建成功,则父进程关闭读通道,输出parentprocesssendsamessagetochild.然后写信息,关闭写通道,输出parentprocesswaitsthechildtoterminate.等待子进程结束。子进程关闭写通道,然后进行读通道。输出themessagereadbychildprocessformparentisamessagetopipe’communication.关闭子进程,输出childprocessterminates。父进程终止输出parentprocessterminates.(3)Linux中的多线程编程threads.c#includepthread.h#includestdio.h#includesys/time.h#includestring.h#defineMAX10pthread_tthread[2];pthread_mutex_tmut;intnumber=0,i;void*thread1()/*线程1*/{printf(thread1:I'mthread1\n);for(i=0;iMAX;i++){printf(thread1:number=%d\n,number);pthread_mutex_lock(&mut);/*声明开始用互斥锁上锁*/number++;/*同一时间只能被一个进程调用*/pthread_mutex_unlock(&mut);/*解锁*/sleep(2);/*休眠2秒*/}printf(thread1:主函数在等我完成任务吗?\n);pthread_exit(NULL);/*线程退出*/}void*thread2()/*线程2*/{printf(thread2:I'mthread2\n);for(i=0;iMAX;i++){printf(thread2:number=%d\n,number);pthread_mutex_lock(&mut);number++;pthread_mutex_unlock(&mut);sleep(3);/*休眠3秒*/}printf(thread2:主函数在等我完成任务吗?\n);pthread_exit(NULL);}voidthread_create(void)/*创建线程*/{inttemp;memset(&thread,0,sizeof(thread));//comment1if((temp=pthread_create(&thread[0],NULL,thread1,NULL))!=0)//comment2printf(线程1创建失败!\n);elseprintf(线程1被创建\n);if((temp=pthread_create(&thread[1],NULL,thread2,NULL))!=0)//comment3printf(线程2创建失败);elseprintf(线程2被创建\n);}voidthread_wait(void)/*等待线程结束*/if(thread[0]!=0){//comment4pthread_join(thread[0],NULL);printf(线程1已经结束\n);}if(thread[1]!=0){//comment5pthread_join(thread[1],NULL);printf(线程2已经结束\n);}}intmain(){pthread_mutex_init(&mut,NULL);/*用默认属性初始化互斥锁*/printf(我是主函数哦,我正在创建线程,呵呵\n);thread_create();printf(我是主函数哦,我正在等待线程完成任务阿,呵呵\n);thread_wait();return0;}结果分析首先有一个线程的标识符,然后用函数pthreadmutexinit生成一个互斥锁。然后通过voidthread_create(void)函数创建线程。在主函数中首先输出:我是主函数哦,我正在创建线程,呵呵,然后执行thread_create();输出:线程1被创建,线程2被创建。然后输出我是主函数哦,我正在等待线程完成任务阿,呵呵。然后线程一线程二交替运行,直至最终结束。本实验中我们使用pthread_mutex_init()函数生成互斥锁来解决变量问题,保证一段时间内只有一个线程在执行一段代码。3.注意:Gcc–lpthread–othread.outthread.c线程相关操作1)pthread_tpthread_t在头文件/usr/include/bits/pthreadtypes.h中定义:typedefunsignedlongintpthread_t;它是一个线程的标识符。2)pthread_create函数pthread_create用来创建一个线程,它的原型为:externintpthread_create__P((pthread_t*__thread,__constpthread_attr_t*__attr,void*(*__start_routine)(void*),void*__arg));第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数。这里,我们的函数thread不需要参数,所以最后一个参数设为空指针。第二个参数我们也设为空指针,这样将生成默认属性的线程。对线程属性的设定和修改我们将在下一节阐述。当创建线程成功时,函数返回0,若不为0则说明创建线程失败,常见的错误返回代码为EAGAIN和EINVAL。前者表示系统限制创建新的线程,例如线程数目过多了;