Linux编程第二版微课版刘文果习题答案_第1页
Linux编程第二版微课版刘文果习题答案_第2页
Linux编程第二版微课版刘文果习题答案_第3页
Linux编程第二版微课版刘文果习题答案_第4页
Linux编程第二版微课版刘文果习题答案_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第1章8.答:ls–a显示当前目录下所有文件信息,包括隐藏文件,而”.”、”.”分别为当前目录及其父目录,是从当前目录下可以访问的,因此作为两个项目放置在当前目录列表中。9.答:当前用户为can,当前工作目录为/home/can/work时,则文件/home/can/work/lib/wrapper.h的相对路径是lib/wrapper.h,文件~/a.out的绝对路径是/home/can/work/a.out。12.答:(1)mkdirworkcp-rf/home/NachOS-4.1work(2)rm-rf/home/can/work/NachOS-4.1/14.答:(1)0644(2)rwxr-xr-x,075515.答:(1)rmf**.o(2)ls??20.答:命令及输出当前用户对目录/root缺少何种缺陷所致$cd/rootbash:cd:/root:Permissiondenied缺少x权限$ls/rootls:cannotopendirectory/root:Permissiondenied缺少r权限$mkdir/root/workmkdir:cannotcreatedirectory‘/root/work’:Permissiondenied缺少w权限21.答:(1)john的家在/home/john;root的家在/root(2)若当前工作目录是/home/john,mike的相对路径为../mike,绝对路径为/home/mikeusr的相对路径为../../usr,绝对路径为/usr第3章17.解: 4complexparampraram2param1PHONE=10086第4章1.答:modeumask实际权限077700220755066600770600S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTHS_IWGRP|S_IWOTH06443.答:(1)abcd(2)abcd1234ijklmnopqrstuvwxyz4.答:定位前位置定位操作定位后指针位置50lseek(fd,20,SEEK_SET);2050lseek(fd,-20,SEEK_SET);5050lseek(fd,-20,SEEK_CUR);3050lseek(fd,20,SEEK_END);7050lseek(fd,120,SEEK_END);17050lseek(fd,-120,SEEK_CUR);505.答:ABCDEFGHIJ12345OPQRST8.答:123456799.答:会包含乱码,因为结构体中的整数20、2000、25、3000以二进制形式写入文件后,gedit以文本方式打开时,这些值可能不是可打印字符。10.答:将变量所在存储区内容直接写入文件,占据文件存储区会小一些,而转换成字符串写入时,文件会大一些。11.答:f2出现乱码,因为文件f2的内容是整数30000的值,2个字节,16进制字节值分别为0xC3和0x50,其中C3超过了7f,将显示为乱码。14.答:fd3=415.答:fd1=3fd4=4fd3=5fd4=016.答:intfd;fd=open("dup2.c",O_RDONLY,0);dup2(fd1,0)18.答:先从1号磁盘块读出”/”的目录表,找到etc行,获得etc目录表所在磁盘块号7;然后将7号磁盘块度如内存,从中找到passwd行,获得passwd数据所在磁盘块号192;最后将192号磁盘块内容读入内存,从中读出passwd第1行19.答:INT(pos/512)20.答:先归还文件分配给f2存储数据的磁盘块2和7,再在can的目录表中删去f2的属性行21.答:(1)相对块号为:INT(1000/512)=1INT(1499/512)=2对应的盘块号为7、11因此,需读盘2次,将7、11号盘块读入内存。(2)相对块号为:INT(2000/512)=3INT(2499/512)=4对应的盘块号为25、87因此,需执行2次读盘和2次写盘操作,磁盘块25、87被更新了。22.答:(1)254*64/512=31.75,分解前查找该目录中某个文件控制块的平均访问磁盘次数为16.5254*10/512=4.96,分解后查找该目录中某个文件控制块的平均访问磁盘次数为4(2)26.答:设置一个当前目录,可大大减少打开一个文件时,需要搜索的目录数。27.答:(1)逻辑地址磁盘块号019120221322(2)INT(1000/512)=1,在20号盘块中28.解:(1)逻辑地址磁盘块号0911621310425(2)INT(1000/512)=1,数据在16号盘块中(3)略29.解:(1)256MB/4KB=64K64K*16/2=128KB(2)500MB/1KB=500K500K*16/2=1MB30.解:(10+1024+10242+10243)×4KB=40KB+4MB+4GB+4TB31.解:(1)INT(9000/4K)=2,数据块的磁盘块号登记在addr(2)中,为直接索引,仅需读1个磁盘块(2)INT(180000/4K)=43,数据块登记在一级间接索引块状,需读2次磁盘块(3)INT(4200000/4K)=1025,1025-10<1023,数据块登记在一级间接索引块状,需读2次磁盘块32.解:(1)分配34、54号磁盘块(2)将行18、列12的位清033.解:(1)12、56、49、50、51(2)334、404、405、782答:loc1=10ch=k,loc2=27(1)k*sizeof(T)K*sizeof(T)lseek(fd,k*sizeof(T),SEEK_SET);read(fd,&c,sizeof(T));39.Tvar[N];void*p=(void*)var;intfd=open(“data”,O_WRONLY);intnum=N*sizeof(T)/B;intremain=N*sizeof(T)%B;for(i=0;i<num;i++){write(fd,p,B);p=p+B;}if(remain)write(fd,p,remain);40.答:open()执行过程:当程序中执行open函数打开时文件时,系统首先检查该文件的v_node是否存在,若不存在,则先为其创建其v_node,将文件的属性从外存读入v-node;接着,创建其文件表(filetable)表项,设置读写方式、读写位置、v-node指针,访问计数器置为1;然后,在进程的描述符表中找到索引号最小的空闲表项,在其中填入文件表表项的指针,返回描述符表项的索引号。close()执行过程:先检查fd指向的文件对象,其计数器大于1,则减1,否则撤销文件对象;然后检查对应的v-node,如果其计数器大于1,则减1,否则撤销v-node;最后将fd对应的描述符置为空闲。如果撤销v-node,应将变化后的内容更新到外存。41.答:Theoldfd1filedescriptor=3Theoldfd2filedescriptor=4Thenewfdfiledescriptor=5Thenewfd2filedescriptor=0Ihavereadfroma.txt:abcdefgh42.答:060143.解:89abc44.答:fd1=3fd2=4fd3=345.答: fd2=546.答: c1=s c2=s47.解: fd2=4 fd3=048.解:2016LINUXEXAMGOOD!GOOD!49.解:(1)M=(M2-M1)/N(2)func真实执行时间T测量误差δ=|Δ1+Δ2|/N,由于Δ1为不变值,通过增大N可减少测量误差50.ddif=/dev/zeroof=file.incount=2048bs=2048readp.c:#include<stdio.h>#include<sys/time.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>intmain(){structtimevalstart,end;inti;charc;doubleusec;intfd=open("file.in",O_RDONLY,0);gettimeofday(&start,NULL);for(i=0;i<1024*1024;i++)read(fd,&c,1);gettimeofday(&end,NULL);close(fd);usec=(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec);usec=usec/(1024*1024);printf("timeofexecteonereadoperation:%lfus",usec);}timeofexecteonereadoperation:0.536409usfreadp.c#include<stdio.h>#include<sys/time.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>intmain(){structtimevalstart,end;inti;charc;doubleusec;FILE*fp=fopen("file.in","r");gettimeofday(&start,NULL);for(i=0;i<1024*1024;i++)fread(&c,1,1,fp);gettimeofday(&end,NULL);fclose(fp);usec=(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec);usec=usec/(1024*1024);printf("timeofexecteonefreadoperation:%lfus\n",usec);}timeofexecteonereadoperation:0.060057us51.答:100/512=19.53逻辑块号为1954.(3)intread(intfd,void*buf,size_tlen){start=pos/BSIZE;end=(pos+len-1)/BSIZE;if(start==end){readBlock(fd,n,b);memcpy(buf,b+pos%BSIZE,len);}else{p=buf;for(i=start;i<=end;i++){readBlock(fd,n,b);if(i==start){memcpy(p,b+pos%BSIZE,BSIZE-pos%BSIZE);p=p+BSIZE-pos%BSIZE;}elseif(i==end){memcpy(p,b,pos%BSIZE);p=p+BSIZE-pos%BSIZE;}else{memcpy(p,b,BSIZE);p=p+BSIZE;}}}returnlen;}53.答:分解式目录当前目录54.解:(1)pos,pos+len-1(2)~55.解:(1)pos,pos+len-1(2)~56.解:(1)500/8=62.5,需要63字节(2)32i+j57.解:(1)起始字节相对块号9000/4096=2,末字节相对块号10499/4096=2,为2号数据块,其磁盘块号位于addr(2),仅需读1次磁盘块。(2)起始字节相对块号180000/4096=43即43号块,末字节相对块号181499/4096=44,为44号块,这两个数据块的磁盘块号登记在一级索引块中。共需读3次磁盘,2个数据块,1个索引块。(3)起始字节相对块号4200000/4096=1025,末字节相对块号4201499/4096=1025,所读数据位于1个数据块中,10<1025<1034,该数据块的磁盘块号位于一级索引块中,需读盘1次,1个数据块,1次索引块. 58.解:(1)3454(2)(62,8)(3)intalloc(){inti,j;for(i=0;i<N;i++)if(bm[i]!=(1<<16)-1)break;for(j=0;j<16;j++)if(bm[i]&1<<j)==0){bm[i]=bm[i]|1<<j;return16*i+j;}voidrelease(intn){inti=n/16,j=n%16;bm[i]=bm[i]&~(1<<j)}59.答:14160.答:(1)文件Wang的路径是/D/DC/DDA/Wang(2)系统需要读取4个目录文件后才能查到Wang:/、/D、/D/DC、/D/DC/DDA(3)系统找到文件Wang,至少需读7个磁盘块(4)采用分解法管理文件目录61.答:组织方式在开始增加一块在中间增加一块在末端增加一块在开始删除一块在中间删除一块在末端删除一块连续1015119949或500链接150100150100单级索引111000第5章5.1答:ABBC5.2答:无运行阻塞状:运行中才能执行等待事件的操作无阻塞就绪状:等待事件发生后,CPU可能被其他进程占用,被唤醒进程加入就绪队列,就不会出现冲突5.3答: scanf:导致调用进程从运行到阻塞 fork:导致调用进程从运行到就绪 read、write、、wait、sleep、pause:导致调用进程从运行到阻塞 exit:导致调用进程从运行到终止5.9答:父:x=0子:x=2x=15.11答: 只有p1和p11一定并发5.12答exfork1.c:16行exfork2.c:4行exfork3.c:无穷多行5.14答:6种:abcbcacabacbbaccba5.15答:3种Hello10Bye2ByeHello01Bye2ByeHello1Bye02Bye5.20答:1)x=0;y=10;z=y/x;2)int*p;*p=100;5.25答:可能输出结果:2种2111215.26.答:(1)包含哪些属性:…(2)不可少属性:进程状态、存储器信息、CPU现场信息5.27.答:就绪:进程获得除CPU之外的所有资源,一旦获得CPU即可运行运行:进程获得所需一切资源,正在CPU上运行阻塞:进程在等待资源或事件5.28答:(1)运行到就绪:时间片用完(2)创建到就绪:执行fork(3)运行到阻塞:printf、scanf、read(4)阻塞到就绪:用户提供了输入、printf输出完成、进程获得read想读的信息(5)运行到终止:调用exit、调用abort、收到9号信号、用户按下Ctrl_C5.29答:进程控制块进程状态进程队列fork创建一个新PCB新PCB状态为ready新PCB进入就绪队列exit当前进程归还多数系统资源当前进程状态变为终止状态运行进程从运行队列退出wait被回收进程PCB撤销调用进程进入阻塞状态调用进程进入阻塞队列5.30答:905.33答:10行5.34答:6行5.35答:三种:4324232435.36答:3行5.37答:2n行5.38答:12钟 axbcaxcbbcaxcbaxbaxccaxb acxbacbxabxcabcxacbxabcx5.39答:5.40答:5.41答:234hellofatherprocess5.42答:原因:用户点按Cntl_C时,子进程收也先收到了SIGINT信号,按缺省方式处理而终止,当父进程向子进程发送SIGINT信号时,子进程已经终止修改方法是创建子进程前,忽略SIGINT信号,代码如下:pid_tpid;voidpa(intsig){kill(pid,SIGUSR1);}voidchild(intsig){if(sig==SIGUSR1){printf("killedbypaprocess);exit(0);}intmain(){signal(SIGINT,SIG_IGN);pid=fork();if(pid==0){usleep(1);signal(SIGUSR1,child);pause();exit(0);}else{signal(SIGINT,pa);pause();exit(0);}}5.43答:ACE5.45答:(1)父子进程都有两种输出:abcdefghij(2)abcde(3)cdefgefghijklmn5.46.答:父进程:90子进程1:30子进程2:80 第6章6.2.答:A.原因是对等线程尚未执行printf操作,主线程执行exit(0)已经让进程终止了,进程终止时也终止了所有线程B.pthread_exit(NULL)或pthread_join(tid,NULL);C.仅去掉exit(0)并不能修复该错误,因为如果一个程序的main函数最后没有exit(0)函数调用,编译程序会自动添加exit(0)函数调用6.3.答:主线程和对等线程每执行一次循环迭代就调用printf函数输出一行,就执行usleep睡眠阻塞,放弃CPU,另一个线程获得CPU也执行一次循环迭代,调用printf打印一行,这样两个线程的输出就交错显示。6.5答:(1)变量运行实例有:pointer,i.m,tid.m,messages[0].m,messages[1].m,vargp.t0,vargp.t1,mytid.t0,mytid.t1,count(2)变量运行实例引用情况:pointer:m,t0,t1messages[0].m:m,t0messages[1].m,:m,t1count:t0,t1tid.m:main,i.m:mainmytid.t0,vargp.t0:t0mytid.t1,vargp.t1:t1(3)共享变量有:pointer,messages[0].m,messages[1],count6.6答:模式1结果模式3结果模式5结果S1柜台1卖出票号8S1柜台1卖出票号8S2柜台2卖出票号8T1ticket=7S2柜台2卖出票号8S1柜台1卖出票号8S2柜台2卖出票号7T1ticket=7S2ticket=7T2ticket=6T2ticket=6T2ticket=6模式2结果模式4结果模式6结果S2柜台2卖出票号8S2柜台2卖出票号8S1柜台1卖出票号8T2ticket=7S1柜台1卖出票号8S2柜台2卖出票号8S1柜台1卖出票号7T2ticket=7T2ticket=7T1ticket=6T1ticket=6T1ticket=66.7.答:步骤线程指令%eax1%eax2count11H1--021R10-032H20-042R200052C201062W201171C111181W111191T1111102T21116.8.答:随niters增大,循环和用时不断增加,很难在分配给线程的一个CPU时间片内完成循环的执行,在执行序列R1、C1、W1或R2、C2、W2中间发生CPU切换,因此开始出现错误结果。6.9.答:(1)线程1的指令R1或R1、C1后,该线程时间片用完,CPU分配给线程2使用;(2)CPU切换的时机有:中断到达、优先级更高的任务到达等。6.10.答:答:(1)原语:原因一般是操作某种特殊共享变量的例程,一般有操作系统内核实现,其特点是由系统内核采用某种手段对同一共享变量的原语例程调用完全错开执行,保证执行原语的并发流以非并发方式操作共享变量。(2)原语可用于实现不允许并发执行的函数例程,如信号量的P、V操作以及用于进程在不同状态转换的控制函数。6.11答:max(r-m+n,0)6.12答:答:(1)互斥:任何时候最多只能允许一个线程进入临界区;(2)有限等待:当一个线程在等待队列挂起时,最多等待前面线程完成临界区执行时间;(3)空闲请进:若无线程在临界区执行,一个请求线程立即进入其临界区;(4)让权等待:临界资源忙时,请求线程立即挂起,释放处理器,避免“循环测试”6.13解:设置互斥信号量mutexsemaphoremutex=1;void*increase(void*vargp){unsignedlonglongi,niters=(int)vargp;for(i=0;i<niters;i++){wait(mutex); count++;signal(mutex);}returnNULL;}void*decrease(void*vargp){unsignedlonglongi,niters=(int)vargp);for(i=0;i<niters;i++){wait(mutex); count--;signal(mutex);}returnNULL;}6.14解:semaphoremutex=1;Process_EW(){wait(mutex);Process_EW(){wait(mutex); 过桥;signal(mutex);}Process_WE(){wait(mutex); 过桥;signal(mutex);}semaphoremutex1=mutex2=1,lots=100;//lots为车位数voidpark(){wait(lots);wait(mutex1);进入停车场;signal(mutex1);找到车位停车驶离车位wait(mutex2);出停车场;signal(mutex2);signal(lots);}6.16解:semaphoremutex=1,seats=100;//seats为座位数voidreader(){wait(seats);wait(mutex);进入阅览室;signal(mutex);找到空座位坐下看书wait(mutex);出阅览室;signal(mutex);signal(seats);}6.17.解:semaphores12=s13=s24=s34=0;P1(){P1(){T1;signal(s12);signal(s13);}P4(){wait(s23);wait(s24);P4(){wait(s23);wait(s24);T4;}P3(){wait(s13);T3;sgnal(s34);}P2(){wait(s12)T2;signal(s24);}6.18解:semaphoreplate=1,orange=apple=0;father(){while(1){洗水果wait(plate);放水果if(是苹果)signal(apple);elsesignal(orange);}}Son(){while(1){wait(orrange);取橘子signal(plate);吃水果}}daughter(){while(1){wait(apple);取苹果signal(plate);吃水果}}6.19.解void*counter(void*no){while(1){sem_wait(&mutex);if(tickets>0){ printf("柜台%d卖出一张票,票号为%d\n",(int)no,tickets);usleep(1);tickets--;}else{sem_post(&mutex);break;}sem_post(&mutex);usleep(1);}}6.20.解:sem_tmutex=1;void*increase(void*vargp){unsignedlonglongi,niters=(int)vargp;for(i=0;i<niters;i++){sem_wait(&mutex); count++;sem_post(&mutex);}returnNULL;}void*decrease(void*vargp){unsignedlonglongi,niters=(int)vargp;for(i=0;i<niters;i++){sem_wait(&mutex); count--;sem_post(&mutex);}returnNULL;}voidmain(){…sem_init(&mutex,0,1);..}6.21解:pthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;void*increase(void*vargp){unsignedlonglongi,niters=(int)vargp;for(i=0;i<niters;i++){pthread_mutex_lock(&mutex); count++;pthread_mutex_lock(&mutex);}returnNULL;}void*decrease(void*vargp){unsignedlonglongi,niters=(int)vargp;for(i=0;i<niters;i++){pthread_mutex_lock(&mutex); count--;pthread_mutex_lock(&mutex);}returnNULL;}voidmain(){…sem_init(&mutex,0,1);..}6.24答:因为虽然多线程都应用了共享变量x、r1、r2,但没有对齐进行并发读写操作,因此不需进行同步干预6.25.答:(1)inpos:所有生产者线程共享outpos:所有消费者线程共享buf数组及其元素:所有生产者、消费者线程共享(2)voidThread_Pi()//生产者线程,有k个{intitem;while(1){item=produce();//产生数据wait(slots);wait(mutex1);sbuf_insert(item,buf);//向缓冲区存放数据signal(mutex1);signal(items);}}voidThread_Ci()//消费者线程,有m个{intitem;while(1){wait(items);wait(mutex2);item=sbuf_remove(buf);//从缓冲区取数据signal(mutex2);signal(slots);consume(item);//消费或处理数据}}6.26答:A.p=1,c=1,n>1:两个互斥信号量都可省去B.p=1,c=1,n=1:两个互斥信号量皆可省去C.p>1,c>1,n=1:两个互斥信号量都不可省D.p>1,c=1,n>1:消费者的互斥信号量可省去6.28.答:semaphoremutex=1,locs=2,orange=apple=0;;father(){while(1){洗苹果wait(locs);wait(mutex);放苹果signal(mutex);Signal(orange);}}Mather(){while(1){洗橘子wait(locs);wait(mutex);放橘子signal(mutex);Signal(orange);}}Son(){while(1){wait(orrange);wait(mutex);取橘子signal(mutex);signal(plate);吃水果}}daughter(){while(1){wait(apple);wait(mutex);取苹果signal(mutex);signal(plate);吃水果}}6.29答:ctime_ts()函数包含了共享静态变量----ctime()的返回值所在位置,而可重入函数是没有共享变量的。6.30答:因为各线程执行进度是不可预测的,如果在第15行后就释放存储块,可能这时对等线程还未执行第24行,这样会导致对等线程操作一个不存在的指针,而出现内存越界错误。6.32.答:(1)用静态数组:#defineN4void*thread(void*vargp);intmain(){pthread_ttid[N];inti,*ptr;intno[N];for(i=0;i<N;i++){ no[i]=i; pthread_create(&tid[i],NULL,thread,&no[i]);}for(i=0;i<N;i++) pthread_join(tid[i],NULL);exit(0);}void*thread(void*vargp){intmyid=*((int*)vargp);usleep(1);printf("Outputfromthread%d\n",myid);returnNULL;}(2)好处:效率高一点,不需动态申请存储器不足:存储器用量大一些,因为动态申请存储器会及时将读完线程id号的单元归还系统6.33解:线程数(t)124CPU核数(p)124运行时间(Tp)1208060加速比(S)11.52效率(Ep)100%75%50%6.34答:.(1)共享变量psum64[]、nelems_per_thread:主线程和所有计算线程共享(2)为何不需加锁nelems_per_thread:主线程与对等线程不是并发操作,主线程操作完成后,对等线程才读它对等线程仅对其进行读操作psum64[]的数组元素:一个对等线程先完成赋值后,主线程才读取值,没有发生并发操作6.35.答:没有共享变量6.37答:三种结果:K=20k=30k=106.38答:三种结果:x=5y=10x=5y=15x=15y=106.39答:问题1:flag=16问题2:flag=21问题3:ret=80问题4:flag=65或71或216.41解:(1)对每个进程来说,变量运行实例有:变量实例引用线程mainP0p1p2p3sum√a[]√√√√√cnt[]√√√√√i.main√√√√√tid.main√myid.p0k.povargp.p0√myid.p1k.p1vargp.p1√myid.p2k.p2vargp.p2√myid.p3k.p3vargp.p3√因此,共享变量有i、a[]、cnt[](2)被并发读写的共享变量只有i。6.42.解:semaphoremutex;ProcessA()ProcessA(){Wait(mutex);打印输出;Signal(mutex);}ProcessB(){Wait(mutex);打印输出;Signal(mutex);}ProcessC(){Wait(mutex);打印输出;Signal(mutex);}6.43.解:(1)可能出现错误结果,因为两个进程存在对共享变量的并发操作(2)可能出现金额有三种:100,200,300四种,正确值是200(3)intamount=0;//全局变量,账号余额,初值为0semaphoremutex;voidSave(intm1){Wait(mutex);m1=amount;m1=m1+100;amount=m1signal(mutex);}voidTake(intm2){Wait(mutex);m2=amount;m2=m2-100;amount=m2signal(mutex);}6.44.解:Semaphoremutex1=mutex2=1,baskets=N,sem=100;Customer(){Wait(sem);Wait(baskets);去购物篮Wait(mutex1);进入商场Signal(mutex1);购物结账Wait(mutex2);出商场Signal(mutex2);归还篮子Signal(baskets);Signal(sem);}6.45.解:Semaphoresem=3,mutex=1;Train(){Wait(sem);Wait(mutex);进站Signal(mutex);停车Wait(mutex);出站Signal(mutex);Signal(sem);}46.答:[max(0,m-n),m]6.47.答:信号量值为0,有2个等待进程6.48答:Sem_ts1,s2,s3;void*thread1(void*vargp){inti;for(i=0;i<10;i++){Sem_wait(&s1);Printf(“A”);Sem_post(&s2);}}void*thread1(void*vargp){inti;for(i=0;i<10;i++){Sem_wait(&s2);Printf(“B”);Sem_post(&s3);}}void*thread1(void*vargp){inti;for(i=0;i<10;i++){Sem_wait(&s3);Printf(“C”);Sem_post(&s1);}}intmain(){pthread_tt1,t2,t3;sem_init(&s1,0,1);sem_init(&s2,0,0);sem_init(&s3,0,0);pthread_create(&t1,NULL,thread1,NULL);pthread_create(&t1,NULL,thread2,NULL);pthread_create(&t1,NULL,thread3,NULL);pthread_join(t1,NULL);pthread_join(t2,NULL);pthread_join(t3,NULL);}6.49.ProcessA()ProcessA()Wait(mAC);readF;signal(mAC);}ProcessB(){wait(mBD);readF;signal(mBD);}ProcessC(){Wait(mAC);readF;signal(mAC);}ProcessD(){wait(mBD);readF;signal(mBD);}6.50.解:semaphoreclose=0,stop=0;司机()司机(){while(1){Wait(close);<<启动车辆>><<正常行驶>><<到站停车>>Signal(stop);}}售票员(){while(1){<<关车门>>Signal(close);<<售票>>Wait(stop);<<开车门>>}}6.51.解:Semaphores12=s13=s24=s25=s46=s56=s36=0;T1(){S1;Signal(s12);Signal(s13);}T2(){Wait(s12);S2;Signal(s24);Signal(s25);}T3(){Wait(s13);S3;Signal(s36);{T4(){Wait(s24);S4;Signal(s46);}T5(){Wait(s25);S5;Signal(s56);}T6(){Wait(s36);Wait(s46);Wait(s56);S6;}6.52.Semaphorecage=1,pig=tiger=0;Hunter(){While(1){打老虎Wait(cage);放老虎到笼子中Signal(tiger);}}Famer(){While(1){养猪Wait(cage);放猪与笼子中Signal(pig);}}Restaurant(){While(1){Wait(pig);从笼子中抓猪Signal(cage);}}Zoo(){While(1){Wait(tiger);从笼子中去老虎Signal(cage);}}6.53.解(1)Semaphorecells=1,items=0,odd=0,even=0;R(){while(1){产生一个数nwait(cells);将数n投入缓冲区Bif(n是奇数)signal(odd)elsesignal(even);}}W1(){while(1){wait(odd);从B中取出数nsignal(cells);打印数n}}W2(){while(1){wait(even);从B中取出数nsignal(cells);打印数n}}6.54.答:(1)信号量还是带加减操作的计数器,不同的是这里允许计算值小于0。wait是等待和预留资源,当前返回时,资源成功预留,进程往下执行;signal归还资源,如有等待进程则唤醒之,并将资源直接转给等待进程。因此,用这里定义的信号量和书本定义的信号量来解决同步互斥问题,编程方法完全一致(2)sem的初值是资源数,sem<0时,|sem|为等待资源的进程数6.55.Semaphorecells1=3,cells=3,cell3=2,cells0=0,items1=items2=items3=0,items0=3;P0(){while(1){wait(items0);从M0取一个消息Signal(cells0);加工消息Wait(cell1);将消息发往M1Signal(item1);}}P1(){while(1){Wait(items1);从M1取一个消息Signal(cells1);加工消息Wait(cell2);将消息发往M2Signal(item2);}}P2(){while(1){wait(items2);从M2取一个消息signal(cells2);加工消息wait(cell3);将消息发往M3signal(item3);}}P3(){while(1){wait(items3);从M3取一个消息signal(cells3);加工消息wait(cell0);将消息发往M0signal(item0);}}6.56.解:Semaphorecells=10,items=0,vat=1,well=1,barrels=3;YoungMonki(){Wait(cells);Wait(barrels);取水桶去水井Wait(well);从水井打水Signal(well);回寺庙Wait(vat);向水缸倒水Signal(vat);还水桶Signal(barrels);Signal(items);}OldMonki(){Wait(items);Wait(barrels);取水桶Wait(vat);从水缸取水Signal(vat);Signal(cells);喝水还水桶Signal(barrels);}6.57解:semaphorePA=M-1,PB=N-1,mutex=1; 产品A入库过程{while(1){生产产品A;P(PA);P(mutex);产品A入库V(mutex);V(PB);}产品B入库过程{while(1){生产产品B;P(PB);P(mutex);产品B入库V(mutex);V(PA);}6.58解:semaphoreavail=m,SA=n,SB=n,IA=0,IB=0;装配(){while(1){P(IA)P(IB)装配V(avail)V(avail)}}进货零件A(){while(1){P(avail);P(SA);进货零件AV(IA);V(SB);}}进货零件B(){while(1){P(avail);P(SB);进货零件AV(IB);V(SA);}}6.60.解:voidsbuf_deinit(sbuf_t*sp)/*清理缓冲区*/{/*在下面填写清除缓冲区代码*/Free(sp->buf);Pthread_destroy(&sp->mutex);Pthread_destroy(&sp->slots);Pthread_destroy(&sp->items);}voidsbuf_insert(sbuf_t*sp,intitem)/*向缓冲区队列sp末尾插入数据item*/{/*在下面填写向缓冲区插入数据的代码*/sem_wait(&sp->slots);sem_wait(&sp->mutex);buf[inpos]=item;inpos=(inpos+1)%N;sem_post(&sp->mutex);sem_post(&sp->items);}intsbuf_remove(sbuf_t*sp)/*从缓冲区队列sp移去和返回队首数据项*/{/*在下面填写从缓冲区取一个数据的代码*/intitem;sem_wait(&sp->items);sem_wait(&sp->mutex);item=buf[outpos];outpos=(outpos+1)%N;returnitem;inpos=(inpos+1)%N;sem_post(&sp->mutex);sem_post(&sp->slots);}6.61.答:不可以。假设同步信号量初值sem=0;在第22行后添加signal(sem),第5行前添加wait(sem)。如果进程连续产生了两个子进程,但仅执行一次addworder,将第1个子进程添加到工作进程池,但第2个子进程先终止,父进程执行信号处理函数,调用rmworkder(pid)时,因子进程2尚未添加到工作进程池而出错。6.62.不可以因为主线程for语句中的操作i++与对等线程的操作intmyid=*((int*)vargp);并发访问共享变量i。i++前后很难加wait、signanl调用。63,64.答:semaphoremutex1=mutex2=wmutex=1;intcount1=count2=0;EasttoWest(){wait(mutex1);count1++;if(count1==1)wait(wmutex);signal(mutex1);汽车走过单行道wait(mutex1);count1--;if(count1==0)signal(wmutex);signal(mutex1);}WesttoEaset(){wait(mutex2);count2++;if(count2==1)wait(wmutex);signal(mutex2);汽车走过单行道wait(mutex2);count2--;if(count2==0)signal(wmutex);signal(mutex2);}6.66解:semaphorecustomers=barbers=0,mutex=0;intwaiting=0;barber(){while(1){wait(customers);//等待顾客,睡觉wait(mutex);waiting=wating-1;signal(barbers);//唤醒一个等待顾客signal(mutex);<<理发>>}}Customer(){wait(mutex);if(waiting<n){waiting=waiting+1;signal(customer);//告知理发师signal(mutex);wait(barbers);//坐下等待理发<<接受理发服务>>exit(0);//离开理发店}signal(mutex);//直接离开}6.67.答:(1)是线程安全函数,也是可重入函数(2)、(3)、(4)都不是线程安全函数,因为都有共享变量,也不是可重入函数改写成线程安全函数方法:(2)程序2:staticintsum_value=0;voidsum_counter(){wait(mutex);sum_value++;signal(mutex);}(3)程序3:char*strtoupper(char*string){charbuffer[MAX_STRING_SIZE];intindex;for(index=0;string[index];index++)buffer[index]=toupper(string[index]);buffer[index]=0;returnbuffer;}(4)程序4:externunsignedcharkey;

voidciphher(char*str){

inti;wait(mutex);for(i=0;str[i];i++)str[i]=(str[i]+key)%256;key=(key+1)%256;signal(mutex)

}改写后,(3)是可重入函数6.69.解:pthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;structhostent*gethostbyname_ts((constchar*name,hostent*he){pthread_mutex_lock(&mutex);memcpy(he,gethostbynam(name),sizeof(structhostent));pthread_mutex_unlock(&mutex);}6.70.解:

#include"wrapper.h"void*increase(void*arg);void*decrease(void*arg);/*全局共享变量*/longlongintcount1=count2=count=0;intmain(intargc,char**argv){unsignedlonglongintniters;pthread_ttid1,tid2;/*检查命令行参数合法性*/if(argc!=2){printf("usage:%s<niters>\n",argv[0]);exit(2);}/*将字符串argv[1]转换成longlong类型*/niters=atoll(argv[1]);/*创建线程并等待其终止*/pthread_create(&tid1,NULL,incease,(void*)niters);pthread_create(&tid2,NULL,decrease,(void*)niters);pthread_join(tid1,NULL);pthread_join(tid2,NULL);count=count1+count2;/*验证结果*/if(count!=0) printf("BOOM!count=%d\n",count);else printf("OKcount=%d\n",count);ex

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论