Linux进程管理与控制课后作业

1、给出导致进程状态转换的事件:

(1)运行→就绪,1种;

(2)创建→就绪,1种;

(3)运行→阻塞,3种;

(4)阻塞→就绪,3种;

(5)运行→终止,4种

答:

(1)调度器分配的时间片已被进程使用完

(2)进程fork()后

(3)进程进行系统服务请求(如I/O请求)

(4)进程进行系统服务请求已完成

(5)进程已结束正常返回,进程发生异常,收到终止信号

2、结合进程结构和进程队列管理,说明fork、exit、wait等系统调用内核函的执行会导致进程控制块、进程状态、进程队列发生何种变化?

fork():创建一个PCB,进程状态变为就绪,加入该进程到就绪队列中

exit():删除该PCB释放资源,进程状态变为终止,将该进程从运行队列中删除

wait():进程状态变为阻塞,将该进程转移到阻塞队列

3、画出下列程序的并发关系图,分析下列程序有几种可能的输出序列?

int main(){
    
    
	if (fork() ==0){
    
    
    	printf ("A");
		printf("B");
    	exit(0);
	}
	else{
    
    
    	if (fork() ==0){
    
    
    		printf ("C");
			printf("D");
    		exit(0);
		}
    	else{
    
    
    		printf ("E");
			printf("F");
    		exit(0);
		}
	}
}

在这里插入图片描述

可能的输出序列:

ABCDEF

ABEFCD

CDEFAB

CDABEF

EFABCD

EFCDAB

ACDEFB

4、编写一个程序,创建子进程,在子进程中执行“ps -A”命令,父进程等待子进程结束后打印“child over” 及处理的子进程号。

#include<unistd.h>
#include<cstdlib>
#include<sys/types.h>
#include<sys/wait.h>
#include<iostream>

using namespace std;

int main()
{
	pid_t pid;
	if ((pid = fork()) == 0) //创建Linux子进程
	{
		char* execv_str[] = {"ps", "-A",NULL};
		if (execv("/usr/bin/ps", execv_str) < 0) //调用ps -A
		{
			perror("error on exec");
			exit(-1);
		}
		exit(0);
	}
	else //父进程
	{
		wait(NULL);//等待子进程结束
		cout<<pid<<": child over" << endl;
		exit(0);
	}
}

运行结果:

在这里插入图片描述

5、编写一个程序,创建如图5-25所示的进程族亲结构,其中p1是程序启动时由加载程序创建的第一个进程。各进程的输出信息分别如下:

在这里插入图片描述

图5-25进程族亲结构
pl: lam father process
p11: I am elder brother process
p12: I am young brother process
p121: I am eldergrandson process
pl22: I am younger grandson process
#include<unistd.h>
#include<cstdlib>
#include<sys/types.h>
#include<iostream>

using namespace std;

int main()//p1
{
	cout << "I am father process." << endl;
	if (fork() == 0)//创建p11
	{
		cout << "I am elder brother process." << endl;
		exit(0);
	}
	else
	{
		if (fork() == 0)//创建p12
		{
			cout << "I am young brother process." << endl;
			if (fork() == 0)//创建p121
			{
				cout << "I am elder grandson process." << endl;
				exit(0);
			}
			else
			{
				if (fork() == 0)//创建p122
				{
					cout << "I am young grandson process." << endl;
					exit(0);
				}
				exit(0);
			}
		}
		exit(0);
	}
}

运行结果:

在这里插入图片描述

6、画出下列程序的进程族亲关系图,给出程序输出多少个hello 行

# include <unistd.h>
int main
{
    
    
    int 1;
    fork();
    i = fork();
    if (i> 0)
        fork();
    if (i> 0)
        fork();
    printf("hello\n");
}

在这里插入图片描述

输出8行

7、分析下列程序输出多少个hello 行

#include "wrapper.h"

void callit()
{
    
    
	fork();
    printf("hello\m");
	if(fork()>0)
		exit(0);
	else
		printf("hello\n");
	return;
}
int main()
{
    
    
	callit();
	printf("hello\n");
	exit(0);
}

输出6行

8、分析下列程序有哪几种可能的输出

#include"wrapper.h"

int main()
{
    
    
    int x = 3;
    if (fork() != 0)
        printf("x=%d\n",++x);
   	printf("x=%d\n",--x);
    return 0;
}

243、423、432

9、分析下列程序输出多少个hello 行

#include"wrapper.h"

void callit()
{
    
    
    pid_t pid;
    pid = fork();
    if (pid == 0)
        printf("hello\n");
    return;
}

int main()
{
    
    
    callit();
    printf("hello\n");
    exit(0);
}

输出3行

10、下面的函数打印多少行输出?用一个关于n的函数表述。假设 n>=1。

void callit()
{
    
    
    int i;
    for (i = 0; i < n; i++)
        fork();
     printf("hello\n");
    exit(0);
}

行数 = 2 ^ n

11、分析下列程序输出序列有哪些?

int main
{
    
    
    if (fork()==0){
    
    
        printf("a");
		printf("x");
    }
    else
    	if (fork()==0)
        	printf("b");
		else
    		printf("c");
}

cbax、bcax、axbc、axcb、baxc、caxb、cabx、bacx、acxb、abxc、abcx、acbx

12、阅读下面的并发程序,计算该计算机有多少种可能输出顺序。

int main()
{
    
    
    if(fork() == 0)
    {
    
    
        printf("A1\n");
        printf("A2\n");
        ...
        printf("An\n");
        exit(0);
    }
    else
    {
    
    
        printf("B1\n");
        printf("B2\n");
        ...
        printf("Bn\n");
        exit(0);
    }
}

答案:
C m + n n C_{m+n}^{n} Cm+nn

13、假设三个并发进程P1、P2、P3分别有操作序列S1、S2、…、Sn 和 T1、T2、…、Tn 以及 U1、U2、…、Un,这些操作有多少种不同的并发执行顺序?

答案:
C m + n + k k C m + n n C_{m+n+k}^{k}C_{m+n}^{n} Cm+n+kkCm+nn

14、考虑下面的程序:

void end(void) {
    
     printf("2"); }
int main()
{
    
    
    if(fork() == 0)
        atexit(end);
    if(fork() == 0)
        printf("0");
    else
        printf("1");
    exit(0);
}

ACE

15、写一个程序,由父进程创建两个子进程,通过在终端输入“Ctrl+\”组合键向交进程发送 SIGQUIT软中断信号或由系统时钟产生 SIGALRM软中断信号,发送给父进程;父进程接收到这两个软中断的其中一个后,向其两个子进程分別发送整数值为16和17的软中断信号,子进程获得对应的软中断信号后,终止运行;父进程调用wait函数等待两个子进程终止,然后自我终止。

#include<unistd.h>
#include<cstdlib>
#include<sys/types.h>
#include<iostream>
#include<sys/wait.h>
#include<signal.h>

using namespace std;

void sigDo(int sig);//收到信号的行为

pid_t pid1; //子进程pid
pid_t pid2; //子进程pid

int main()
{
    
    
	if ((pid1 = fork()) == 0) //创建第一个子进程
	{
    
    
		cout << "elder process is running!" << endl;
		signal(SIGQUIT, SIG_IGN);//忽略SIGQUIT信号
		signal(SIGSTKFLT, sigDo);//修改SIGSTKFLT信号(16)的行为
		pause();
	}
	else
	{
    
    
		if ((pid2 = fork()) == 0) //创建第二个子进程
		{
    
    
			cout << "young process is running!" << endl;
			signal(SIGQUIT, SIG_IGN);;//忽略SIGQUIT信号
			signal(SIGCHLD, sigDo);//修改SIGCHLD信号(17)的行为
			pause();
		}
		//修改信号SIGQUIT的行为
		signal(SIGQUIT, [](int sig)->void
			{
    
    
				cout << "sent" << endl; 
				kill(pid1, SIGSTKFLT);
				kill(pid2, SIGCHLD);
			});
		wait(NULL);//等待子进程结束
		cout << "main exit" << endl;
		exit(0);//主进程结束
	}
}

void sigDo(int sig)
{
    
    
	cout << sig << ": exit" << endl;
	exit(0);
}

在这里插入图片描述

16、阅读下面的程序,假设数据文件data的内容为“ abcdefghijklmnopqrstuvwxyz”,请给出三个程序中父子进程所有可能的输出。

在这里插入图片描述
(1) abcdefghij或fghijabcde 子进程与父进程共享文件指针

(2) abcdeabcde 子进程与父进程不共享文件指针

(3) cdefgjklmnl或jklmnlcdefg 子进程与父进程共享文件指针,且调用了两次lseek()

17、阅读下面的程序,分析各个进程的输出是什么

int main()
{
    
    
    int x = 10;
    if(fork() == 0)
        x = x + 20;
    else{
    
    
        x = x + 30;
        if(fork() == 0)
            x = x + 40;
        else
            x = x + 50;
    }
    printf("x=%d\n",x);
}

main:90

子1:30

子2:80

18、Explain the circumstances under which the line of code marked printf(“LINE J”) in the following program will be reached. 解释在何种情况下到达以下程序中标记为printf的代码行(“行J”)。

在这里插入图片描述

答:main进程创建子进程后,子进程将通过exec函数调用shell的ls指令,所以无论什么情况都无法到达printf(“LINE J”)代码行

19、Using the following program, identify the values of pidat lines A, B,C, and D. (Assume that the actual pids of the parent and child are 2600 and 2603, respectively.)使用以下程序,确定行A、B、C和D的PID值(假设父级和子级的实际PID分别为2600和2603)

int main()
{
    
      
    pid_t pidj pidl:
   	pid = fork();  /* fork a child process */
   	if (pid < 0{
    
     /* error occurred */
     	fprintf(stderr, "Fork Failed");
     	return 1;
   	}
   	else if (pid==0) {
    
     /* child process */
     	pid1 = getpid();
     	printf("Child: pid = %d",pid);    /* A */
     	printft("Child: pidl = %d",pid1); /* B */
   	}
   	else {
    
     /* par«nr process •/
     	pid1= getpid();
     	printf("parant: pid = %d",pid); /* C */
     	printf("parent: pidl= %d",pidl); /* D */
     	wait(NULL);
   	}
   	return 0;
}

A = 0、B = 2603、C = 2603、D = 2600

20、Using the following program, explain what the output will be at line X and Y.使用以下程序,解释X和Y行的输出。

在这里插入图片描述

x行输出依次为0,-1,-4,-9,-16

y行输出依次为0,1,2,3,4

子进程是父进程的副本,对子进程变量的修改不会影响到父进程

21、Is it possible to have concurrency but not parallelism? Explain.有可能有并发性,但没有并行性吗?解释一下。

对于单核多任务处理机,仅存在并发,而无法存在并行。


@程序代码均使用Visual Studio 2019作为IDE,通过ssh连接ubuntu20.04使用g++9.3编译
12、13题抄答案的,希望能有大佬讲解一下。

猜你喜欢

转载自blog.csdn.net/Qingyuyuehua/article/details/115277165
今日推荐