实验六 进程基础

项目 内容
这个作业属于哪个课程 2021春季Linux系统与应用(南昌航空大学-信息工程学院)
这个作业的要求在哪里 实验六 进程基础
学号-姓名 18043217-罗生
作业学习目标 (1)掌握Linux系统环境C语言编程概念;(2)学习Linux系统进程概念。

1、请举例说明静态链接库的创建与使用。

ar:静态函数库创建的命令
-c :create
-r :replace
表示当前插入的模块名已经在库中存在,则替换同名的模块;
如果若干模块中有一个模块在库中不存在,ar显示一个错误信息,并不替换其他同名的模块。

实验六 进程基础

实验六 进程基础

实验六 进程基础

实验六 进程基础

2、请举例说明共享库的创建与使用。
开始的目录结构:
实验六 进程基础

观察下面的目录结构,与开始的目录结构对比:

(1)创建共享库
实验六 进程基础
(2)使用自己的共享库
方式一:指定相对路径

实验六 进程基础

方式二:只给链接器动态库名称(若要正常实现,后面必须添加一个环境变量)

实验六 进程基础

3、编程实现一个简单文件复制命令。(文件I/O)

#include <unistd.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h>
#include <stdio.h> 
#define BUFFERSIZE 4096 
int main(int argc, char* argv[]) { 
	if (argc != 3) {
		printf("usage:\n mycp src dst\n"); 
		return 1;
	}
	int srcfd = open(argv[1], O_RDONLY); 
	if (srcfd == -1) { 
		perror("open"); 
		return 1; 
	}
	int dstfd = open(argv[2], O_CREAT | O_WRONLY, 0666);
	if (dstfd == -1) { 
		close(srcfd);
		perror("open"); 
		return 1; 
	}
	int len = 0; 
	char buffer[BUFFERSIZE] = {0};
	while((len = read(srcfd, buffer, BUFFERSIZE)) > 0) { 
		if (write(dstfd, buffer, len) != len) { 
			perror("write error");
        	return 1;
		} 
	}
	if (len < 0) { 
		perror("read error"); 
		return 1;
		}
	close(srcfd); // 关闭文件 
	close(dstfd); 
	return 0; 
}

实验六 进程基础

实验六 进程基础

实验六 进程基础

4、使用 fork 创建一个子进程,进程创建成功后父子进程分别输出不同的内容。
实验六 进程基础

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
	pid_t pid;
	printf("[%d]:Begin! \n",getpid());
	fflush(NULL);
	pid = fork();
	if(pid<0)
	{
		perror("fork()");
		exit(1);
	}
	else if(pid > 0)
	{
		printf("[%d]:Parent process if working!\n",getpid());
	}
	else
	{
		printf("[%d]:Child process if working!\n",getpid());
	}
	printf("[%d]:Finish!\n",getpid());
	return 0;
}

实验六 进程基础

删除fflush(NULL);//查看运行结果区别
./fork1 > /tmp/out 输出结果删除后子程序工作前多个 Begin!
实验六 进程基础

进一步删除15行 \n ,查看运行结果区别
删除后 Begin! 与 父进程、子进程间不换行

实验六 进程基础

5、使用fork创建多个子进程。

int i;
pid_t pid;
for (i = 0; i < 3; i++)
pid = fork();

上面代码段会产生多少子进程?

2^3-1=7
产生7个子进程
实验六 进程基础

实验六 进程基础

使用sleep函数简单控制进程输出顺序

实验六 进程基础

实验六 进程基础

6、在 fork 之前以写的方式创建了一个文件 test.txt。然后 fork 出的子进程立即向文件中写入
“world”,然后睡眠5秒。而父进程在 fork 后睡眠3秒后向 test.txt 写入 "hello",并关闭描述符。子
进程恢复后,又向 test.txt 文件中写入 "lalala"后关闭描述符,结束。

实验六 进程基础

实验六 进程基础

7、分别在主函数中使用
execvp 启动 ls 命令以及使用 fork 函数产生子进程调用 execvp 启动 ls 。

程序调用execvp,实现一个程序运行另一个程序
(1)使用execvp启动ls命令
实验六 进程基础

实验六 进程基础

(2)使用fork函数产生子进程调用execvp启动ls
实验六 进程基础

实验六 进程基础

8、创建5个僵尸进程,并在终端通过 ps axf 命令查看僵尸进程信息。
实验六 进程基础

实验六 进程基础

实验六 进程基础

9、 通过 wait 来清理僵尸进程。
wait(等待子进程中断或结束)
(1)表头文件:

#include<sys/types.h>
#include<sys/wait.h>

(2)定义函数: pid_t wait (int * status);
(3)函数说明:
wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status可以设成NULL。
(4)返回值:
如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1,失败原因存于errno 中。
实验六 进程基础

实验六 进程基础

10、父进程通过 waitpid 函数等待特定子进程结束,若该子进程不结束,父进程一直阻塞。

waitpid
(1)函数功能:用来等待某个特定进程的结束
(2)函数原型:
    pid_t waitpid(pid_t pid, int *status, int options);
(3)参数:
    status如果不为空,会把状态信息写到它指向的位置
    options允许改变waitpid的行为,最有用的一个选项是WNOHANG,它的作用是防止waitpid把调用者的执行挂起.
(4)返回值:成功返回等待子进程的pid,失败返回-1

实验六 进程基础

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
void handler(int sig)
{
	pid_t pid;
	while ((pid = waitpid(-1,NULL,WNOHANG)) > 0)
	{
		printf("wait child sucess : %d\n",pid);
		
	}
}
int main()
{
	signal(SIGCHLD,handler);
	pid_t pid = fork();
	if (pid == 0)
	{
		printf("child1 pid : %d\n",getpid());
		sleep(3);
		exit(1);
	}
	pid_t pid2 = fork();
	if (pid2 == 0)
	{
		printf("child2 pid2 : %d\n",getpid());
		sleep(5);
		exit(2);
	}
	pid_t pid3 = fork();
	if (pid3 == 0)
	{
		printf("child3 pid3 : %d\n",getpid());
		sleep(7);
		exit(3);
	}
	printf("father pid : %d\n",getpid());
	while (1)
	{
		printf("father do self\n");
		sleep(1);
	}
	return 0;
}

实验六 进程基础

上一篇:实验六 进程基础


下一篇:实验六 进程基础