实验2-1
使用fork创建进程
编写程序,使用系统调用fork()创建如下的进程树,当此程序运行时,在系统中有一个父进程和多个子进程活动,父进程等子进程运行结束后退出。
设置变量X=0,每一个进程在屏幕上显示不同的字符串,父进程的字符串内容要包括自己的学号、姓名、变量X的值;子进程字符串要包括进程PID、子进程序号(子进程1或2或3)、变量X的值,循环显示4次。每次循环X的值加2。记录屏幕上的显示结果,并分析变量X的变化规律。
说明:getpid()获得进程的ID。
代码
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
int main()
{
int i=0,X=0;
pid_t pid1,pid2;
pid1 = fork();//创建一个新process
if(pid1 < 0)
{
printf("failed");
exit(1);
}
else if(pid1 == 0)
{
for(int i = 0;i<4;i++)
{
printf("Child_1 PID = %d, X = %d\n",getpid(),X);
X =X + 2;
}
}
else
{
pid2 = fork();//创建第二个新进程
if(pid2 < 0)
{
printf("failed");
exit(1);
}
else if(pid2 == 0)
{
for(int i = 0;i<4;i++)
{
printf("Child_2 PID = %d, X = %d\n",getpid(),X);
X = X + 2;
}
}
else
{
for(int i = 0;i<4;i++)
{
printf("Parent StuID = 2018308250217, X=%d\n",getpid(),X);
X = X +2;
}
}
}
getchar();//为了拦住进程,不让进程结束
return 0;
}
实验2-2
使用exec替换子进程程序
修改任务1编写的程序,将子进程改为独立的程序,父进程创建子进程并进行程序替换,观察程序执行时屏幕出现的现象,并分析原因。
代码
fork.c
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
int main()
{
int i=0,X=0;
pid_t pid1,pid2;
pid1 = fork();//创建一个新process
if(pid1 < 0)
{
printf("failed");
exit(1);
}
else if(pid1 == 0)
{
for(int i = 0;i<4;i++)
{
printf("Child_1 PID = %d, X = %d\n",getpid(),X);
X =X + 2;
}
}
else
{
pid2 = fork();//创建第二个新进程
if(pid2 < 0)
{
printf("failed");
exit(1);
}
if(pid2 == 0)
{
excel("./a.out","fork_1",NULL);
exit(1);
}
else
{
sleep(2);
for(int i = 0;i<4;i++)
{
printf("Parent StuID = 2018308250217, X=%d\n",getpid(),X);
X = X +2;
}
}
}
getchar();//为了拦住进程,不让进程结束
return 0;
}
fork-1.c
#include <stdio.h>
#include <stdlib.h>
#include <unisted.h>
#include <sys/types.h>
int main()
{
int i = 0,X = 0;
pid_t pid;
pid = vfork();
if(pid > 0)
{
for(i = 0; i < 4; i++){
printf("Parent StuID = 2018308250217, X = %d\n",X);
X = X + 2;
}
}
else if(pid == 0)
{
sleep(2);
for(i = 0;i < 4;i++)
{
printf("Child PID = %d, X = %d\n",getpid(),X);
X = X + 2;
}
}
else
{
printf("failed");
exit(1);
}
return 0;
}
实验2-3
分析进程的父进程
在系统中,所有的进程组成一个进程树,但在实际操作中,存在中孤儿进程情况,孤儿进程就是父进程已终止,但是子进程没终止,然后就成孤儿。分析孤儿进程的父进程如何变化。
编写程序,要求如下:
父进程创建子进程;
子进程每2秒输出父进程的ID,一直循环;
父进程3秒后,输出自己的ID,结束进程;
分析程序的运行结果,重点说明子进程的父进程如何变化的。
代码
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
int i;
int pid, ppid;
printf("begin\n");
pid = fork();
if (pid == -1)
{
printf("fork error");
exit(-1);
}
if (pid == 0) //child process
{
for (i=0; i<5; i++)
{
ppid=getppid();
printf("This is child. PID of the parent is %d\n", ppid);
sleep(2);
}
}
else
{
sleep(3);
printf("This is parent. the parent process will stop running\n");
}
printf("end\n");
return 0;
}
实验2-4
共享存储区机制进程通信
编程实现生产者和消费者共享存储区功能。生产者随机产生10个整型数据,写入共享存储区;消费者读出数据,并进行平方和平方根运算后输出。使用系统调用shmget()、shmat()、sgmdt()、shmctl()等, 实现程序。
代码
生产者
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <stdio.h>
#define KEY 75
#define K 1024
main()
{int shmid, *p, i;
char * shmaddr;
shmid=shmget(KEY,K,0777|IPC_CREAT);
shmaddr=shmat(shmid,0,0);
p=(int *) shmaddr;
for(i=0;i<10;i++)
{ *p = rand()%100;
sleep(1);
printf("%d\n",*p);
p++;
}
sleep(5);
shmdt(shmaddr);
shmctl(shmid,IPC_RMID,0);
printf("end\n");
}
消费者
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <stdio.h>
#define KEY 75
#define K 1024
main()
{int mid,*q, *t, i,num;
char *maddr;
mid=shmget(KEY,K,0777);
maddr=shmat(mid,0,0);
q=(int *)maddr;
sleep(6);
for(i=0;i<10;i++)
{
num=(*q)*(*q);
printf("%d\n",num);
q++;
num=0;
}
shmdt(maddr);
shmctl(mid,IPC_RMID,0);
}
实验2-5
消息队列实现进程通信
修改上面的程序。父进程从键盘上接受10个数据,对其求和sum1,子进程求这10个数平方和sum2,使用消息队列方式将结果传给父进程,父进程计算sum1+sum2,打印结果。
代码
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define KEY 100
#define SIZE 10
struct msgform{
long mtype;
char mtext[100];
}msg,smsg;
int main()
{
int num[SIZE];
int shmid,i;
char *shmaddr;
int sum=0;
int *p;
int x;
int msgid;
//use shm to deliver data
shmid=shmget(KEY,sizeof(int)*SIZE,0777|IPC_CREAT);
if(shmid==-1){
printf("shmget erroe!\n");
return;
}
shmaddr=shmat(shmid,NULL,0);
p=(int *)shmaddr;
//input data
for(i=0;i<SIZE;i++){
printf("Input number %d:",i+1);
scanf("%d",p++);
}
p=p-5;
//compute sum of the five numbers
for(i=0;i<SIZE;i++){
sum+=*p++;
}
printf("SUM:%d\n",sum);
//use msg queue to deliver result
msgid=msgget(KEY+1,0777|IPC_CREAT);
if(msgid==-1){
printf("msgget error!");
return;
}
if((x=fork())==-1){
printf("fork error!\n");
return;
}
if(x==0){// child process
int sum_power2=0;
p=p-5;
for(i=0;i<SIZE;i++){
int temp=*p++;
sum_power2=sum_power2+temp*temp;
}
//send data
smsg.mtype=1;
sprintf(smsg.mtext,"%d",sum_power2);
if(msgsnd(msgid,&smsg,100,0)==-1){
printf("msgsnd error!\n");
return;
}
return;
}else{//parent process
wait();
//receive data
msgrcv(msgid,&msg,100,1,0);
printf("square sum:%s\n",msg.mtext);
}
//release resources
msgctl(msgid,IPC_RMID,0);
shmdt(shmaddr);
shmctl(shmid,IPC_RMID,0);
}