JavaSE Zookeeper 数据结构 docker安装部署 webpack timer signalr handlebarsjs vue网页 jquery解析json数据 当前线程等待5秒 maven配置eclipse vim跳到文件末尾 js基本数据类型有哪些 jquery获取兄弟节点 pythonassert函数 python加注释 python中set的用法 python文件读取 java变量类型 java终止线程 java集合框架图 java方法的调用 java文件读取 linux密码忘记 php开发教程 金山wps2003 ** 网络是怎样连接的 圆形截图 cfqq网吧任务 编程语言实现模式 工程html加密 跑马灯动态壁纸 pr书写效果 逗号的作用 海蜘蛛软路由 painter下载 文件分割 hedit
当前位置: 首页 > 学习教程  > 编程语言

进程入门之fork、getpid

2021/1/13 20:29:16 文章标签: 测试文章如有侵权请发送至邮箱809451989@qq.com投诉后文章立即删除

1.进程的基本概念: 问:什么是程序,什么是进程,区别是什么? 答:程序是静态概念,比如gcc test1.c -o a.out,那么a.out就是程序   进程是动态概念,就是程序运行起来后&a…

1.进程的基本概念:

:什么是程序,什么是进程,区别是什么?

:程序是静态概念,比如gcc test1.c -o a.out,那么a.out就是程序
  进程是动态概念,就是程序运行起来后,系统中就多了一个进程

:如果在Linux下查看系统的进程?

ps指令:展示一小部分的进程
在这里插入图片描述

ps -aux指令:展示几乎所有的进程(但是往往又用不到这么些)
在这里插入图片描述
所以我们通常采用ps和grep配合使用的方式来过滤掉一些无用进程,来获取有效信息(Linux中有一个管道,将-aux中的内容顺着管道,在管道末尾进行grep过滤,过去有用的东西):
ps -aux|grep xxx指令
在这里插入图片描述

top指令:相当于是Windows下的任务管理器(是一个动态的界面)

在这里插入图片描述
:什么是进程标识符?

:每个进程都有一个非负整数表示唯一的ID,叫做pid(类似文件标识符)
Pid = 0:成为交换进程(swapper)
    作用是:进程调度(分配内存,CPU占有率等)
Pid = 1:init进程
    作用是:系统初始化(读取配置文件,调用其他进程等)

getpid函数:

调用该函数会返回进程的标识符
包含于头文件:

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

简单的样例:

pid_t pid;
pid = getpid();

:什么是父进程?什么是子进程?

:进程A创建了进程B,A就是父进程,B就是子进程

:C语言的程序空间是如何分配的?

:如图所示:
在这里插入图片描述

2.进程的创建:

创建进程的函数fork:
函数原型:

pid_t fork(void);

fork如果调用成功了的话,会返回两个值:
返回值为0 代表当前进程是子进程
返回值为非负数 代表当前进程是父进程(返回的值是子进程的pid)
返回值为-1 代表调用失败

test1.c的代码如图:

int main(){
	pid_t pid;
	pid = getpid();
	printf("The pid of my process is %d\n",pid);
	return 0;
}

运行结果如图所示:
在这里插入图片描述
通过运行结果我们知道一个问题就是每次创建一个进程。他的pid都是不一样的,是在变化的

test2.c的代码如图所示:

int main(){
	pid_t pid;
	pid = getpid();
	fork();
	printf("The pid of my process is %d\n",pid);
	return 0;
}

运行结果如图所示:
在这里插入图片描述
这样奇怪的知识就增加了,为什么会打印两次?在做一个测试,来看看新打印出来的,fork出的进程和原进程是不是同一个进程,还是父子进程的关系?

test3.c代码如图:

int main(){
	pid_t pid;
	pid = getpid();
	fork();
	printf("The pid of my process is %d\n",pid);
	printf("The pid of fork is %d\n",getpid());
	return 0;
}

运行结果如图所示:
在这里插入图片描述
而在刚开始的时候自己编写test1.c时,出现了一个小错误,代码是这样的

int main(){
	pid_t pid;
	pid = fork();
	printf("The pid of my process is %d\n",pid);
	return 0;
}

运行结果是这样的,有没有发现其中的问题?
在这里插入图片描述
那就是fork返回的值是两个,一个是pid,一个是表明身份的 0(忘了的可以看一下我上面写的内容),0 表示的是子进程啊!这就说明在一个main函数中时fork出来的进程也会并发执行原来的程序,但是却是子进程!

3.子进程存储的方式:

早期Linux是直接将父进程中除了未初始化的数据,全部拷贝给子程序,代码段进行共享;但随着Linux内核的发展完善,现在则是写实拷贝,通俗说就是如果初始化的数据在后边未进行修改的话(保证父子进程数据独立),则共享同一块存储空间


4.创建子进程后程序都在做些什么:

fork之后,先给子进程开辟一块空间,随后系统进行程序调度,决定父与子谁先运行(父、子有可能先运行)

5.创建fork的目的:

  1. 父进程希望子进程复制自己的代码,同时执行不同的代码段。这种应用场景在网络服务进程中是很常见的——父进程等待客户端发来的服务请求,请求到达时,父进程调用fork来创建子进程,让子进程来处理这个服务请求,于此同时父进程继续等待下一个服务请求的到达。就是一个程序想要同时运行多段代码,但是一个程序正常=情况下是不可能完成的,所以创建出另外的程序帮自己来完成,就像鸣人影分身处理事务[doge])
  2. 一个进程要执行不同的程序,这对shell是常见的情况。在这种情况下,子进程从fork返回后要立即调用exec(暂时先了解)

今天最后写一个小程序来巩固以下,粗浅的模拟一下Socket[doge]:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main(){
	pid_t pid,upid;
	int cmd;

	while(1){
		
		printf("Please input your command to this socket!\n");
		scanf("%d",&cmd);
		if(cmd == 1){
			printf("Connecting......\n");
			pid = fork();
	
			if(pid == 0){
				while(1){
					printf("%d is connected\n",getpid());
					sleep(3);
				}
			}else{
				printf("Waiting for the next user!\n");
			}
		}else{
			printf("ERROR!\n");
		}

	}

	return 0;
}

本文链接: http://www.dtmao.cc/news_show_600337.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?