实训1Linux进程管理命令的使用实训目标:(1)掌握Linux中ps命令使用方法。(2)掌握Linux中top命令使用方法。实训内容:(1)使用ps命令查看进程。(2)使用top命令查看进程。实训步骤:(1)使用ps命令查看进程。a.不带参数的ps命令:#psb.带参数的ps命令:#psaux(2)使用top命令查看进程。a.监视特定用户:$top:输入此命令,按【Enter】键,查看执行结果。u:然后输入“u”按【Enter】键,再输入用户名,即可。b.终止指定的进程:$top:输入此命令,按【Enter】键,查看执行结果。k:然后输入“k”按【Enter】键,再输入要结束的进程ID号。实训2Linux进程管理编程(进程的创建)实训目标:掌握fork()系统调用的使用。实训内容:写出如下程序的执行结果,并画出该进程家族树。/***fork()***/#includestdio.hmain(){fork();/*父进程1创建子进程2*/fork();/*父进程返回后分别再创建各自的子进程3、4*/fork();/*父进程1、2、3、4返回后分别再创建各自的子进程5、6、7、8*/putchar(‘A’);/*每个进程都要输出‘A’*/putchar(‘\n’);/*输出‘A’后按【Enter】键换行*/}实训步骤:(1)新建并编辑fork3.c.(2)编译fork3.c。[cathya@stu桌面]$gcc-ofork3fork3.c(3)执行fork3,结果如下。[cathya@stu桌面]$./fork3AAAAAAAA[cathya@stu桌面]$(4)查看该进程执行结果为八个“A”,说明有八个进程产生。其进程关系如图3—8所示。图3—8调用三次fork()的进程家族树步骤2—4的执行结果12354678实训3Linux进程管理编程(父子进程的同步)实训目标:掌握fork()系统调用的使用。实训内容:实现子进程先输出“B”然后父进程再输出“A”,源程序命名为synl.c。实训步骤:(1)编写源文件synl.c为以下内容(执行内容如图1):#includestdio.hmain(){intp1;while((p1=fork())==-1);if(p10){wait(0);//父进程等待子进程终止putchar(‘A’);Putchar(‘\n’);}else{putchar(‘B’);putchar(‘\n’);exit(0);//子进程向父进程发终止信号0}}(2)编译(如图2)。(3)执行(如图2):[cathya@stu桌面]$./synlBA[cathya@stu桌面]$源程序编译连接并多次运行后的结果都是子进程先输出“B”父进程后输出“A”,说明父进程等待子进程的同步关系成立。图1图2实训4Linux进程管理编程(生产者消费者问题)实训目标:掌握Linux关于同步、互斥信号量的使用。实训内容:设父进程创建一个子进程作为生产者,创建两个子进程作为消费者,这三个子进程使用一个共享内存,如图3—9所示,该共享内存定义为具有五个变量的数组,每个变量表示一个缓冲区,缓冲区号为0~4.生产者进程依次往缓冲区0~4中写十个数据1~10,两个读进程依次从缓冲区0~4中轮流取出这10个数据。使用信号量实现进程读写缓冲区的同步和互斥。分析:(1)需要创建三个子进程:生产者、消费者A、消费者B;(2)需要使用三个信号量:empty、full、mutex,分别表示缓冲区是否有空、是否有数和互斥信号量,其初值分别为:5,0,1;(3)需要两个共享内存:array和get,分别表示多缓冲区数组变量array[0]~[4]和消费者读缓冲区号的计数get,get计数由两个消费者进程共享,由于生产者只有一个,所以写缓冲区的计数set不需要使用共享内存。实训步骤:(1)新建并编辑编写源文件为以下内容:#includesys/types.h#includelinux/sem.h#includelinux/shm.h#includeunistd.h#includestdio.h#includeerrno.h#includetime.h#defineMAXSHM5//定义缓冲区数组的下标变量个数/******定义信号量的内部标识******/intfullid;intemptyid;intmutexid;intmain(){/******定义共享内存的ID******/intarrayid;intgetid;/******定义共享内存虚拟地址******/int*array;int*get;/******创建共享内存******/arrayid=shmget(IPC_PRIVATE,sizeof(int)*MAXSHN,IPC_CREAT|0666);getid=shmget(IPC_PRIVATE,sizeof(int),IPC_CREAT|0666);/**********初始化共享内存********/array=(int*)shmat(arrayid,0,0);get=(int*)shmat(getid,0,0);*get=0;/*定义信号量数据结构*/structsembufP,V;unionsemunarg;/*创建信号量*/fullid=semget(IPC_PRIVATE,1,IPC_CREAT|0666);emptyid=semget(IPC_PRIVATE,1,IPC_CREAT|0666);mutexid=semget(IPC_PRIVATE,1,IPC_CREAT|0666);/*初始化信号量*/arg.val=0;//初始时缓冲区中无数据if(semctl(fullid,0,SETVAL,arg)==-1)perror(semctlsetvalerror);arg.val=MAXSHM;//初始时缓冲区中有5个空闲的数组元素if(semctl(emptyid,0,SETVAL,arg)==-1)perror(semctlsetvalerror);arg.val=1;//初始时互斥信号为1,允许一个进程进入if(semctl(mutexid,0,SETVAL,arg)==-1)perror(semctlsetvalerror);/*初始化PV操作*/P.sem_num=0;P.sem_op=-1;P.sem_flg=SEM_UNDO;V.sem_num=0;V.sem_op=1;V.sem_flg=SEM_UNDO;/*生产者进程*/if(fork()==0){inti=0;intset=0;while(i10){semop(emptyid,&P,1);//对emptyid执行P操作semop(mutexid,&P,1);//对mutexid执行P操作array[set%MAXSHM]=i+1;printf(Producerputnumber%dtoNo.%d\n,array[set%MAXSHM],set%MAXSHM);set++;//写计数加1semop(mutexid,&V,1);//对mutexid执行V操作semop(fullid,&V,1);//对fullid执行V操作i++;}sleep(3);//等待消费者进程执行完毕printf(Poducerifover\n);exit(0);}else{/*消费者A进程*/if(fork()==0){while(1){if(*get==10)break;semop(fullid,&P,1);//对fullid执行P操作semop(mutexid,&P,1);//对mutexid执行P操作printf(TheConsumerAgetnumberfromNo.%d\n,(*get)%MAXSHM);(*get)++;//读计数加1semop(mutexid,&V,1);//对mutexid执行V操作semop(emptyid,&V,1);//对fullid执行V操作sleep(1);}printf(ConsunerAisover\n);exit(0);}else{/*消费者B进程*/if(fork()==0){while(1){if(*get==10)break;semop(fullid,&P,1);//对fullid执行P操作semop(mutexid,&P,1);//对mutexid执行P操作printf(TheConsumerAgetnumberfromNo.%d\n,(*get)%MAXSHM);(*get)++;//读计数加1semop(mutexid,&V,1);//对mutexid执行V操作semop(emptyid,&V,1);//对emptyid执行V操作sleep(1);}printf(ConsunerBisover\n);exit(0);}}}/*父进程返回后回收3个子进程*/wait(0);wait(0);wait(0);/*断开并撤消2个共享内存*/shmdt(array);shmctl(arrayid,IPC_RMID,0);shmctl(get);shmctl(getid,IPC_RMID,0);/*撤消3个信号量集*/semctl(emptyid,IPC_RMID,0);semctl(fullid,IPC_RMID,0);semctl(mutexid,IPC_RMID,0);exit(0);}(2)编译源程序。(3)执行。由运行结果可以看出,生产者进程分别往缓冲区0~4中送了十次产品,消费者进程A和B轮流从缓冲区0~4中取走和产品,并实现了三个进程之间的同步和互斥,即视线里生产者进程送了产品后消费者进程才取走产品,并且一次只有进程进入缓冲区。步骤1.1步骤1.2步骤1.3步骤1.4步骤2、3