用以下指令查找正在运行的进程,并使用 grep
过滤出包含 "int" 的行。 "ps -aux" 显示当前系统上所有用户的进程列表,而 grep
命令则筛选出包含 "int" 的行。
ps -aux|grep int
p代表process进程
1.什么是程序,什么是进程,有什么区别?
程序是静态的概念,gcc xxx.c –o pro 磁盘中生成pro文件,叫做程序。
进程是程序的一次运行活动, 通俗点意思是程序跑起来了,系统中就多了一个进程。
2.如何查看系统中有哪些进程?
a.使用ps指令查看 实际工作中,配合grep来查找程序中是否存在某一个进程。
b.使用top指令查看,类似windows任务管理器。
3.什么是进程标识符?
每个进程都有一个非负整数表示的唯一ID, 叫做pid,类似身份证
Pid=0: 称为交换进程(swapper) 作用—进程调度。
Pid=1:init进程 作用—系统初始化。
编程调用getpid函数获取自身的进程标识符 getppid获取父进程的进程标识符。
4.什么叫父进程,什么叫子进程?
进程A创建了进程B 那么A叫做父进程,B叫做子进程,父子进程是相对的概念,理解为人类中的父子关系。
C程序的存储空间分配可以分为以下几个部分:
-
代码区(Text Segment):代码区存储程序的机器代码,也就是编译后的可执行指令。这部分通常是只读的,并且在程序运行时不可修改。
-
数据区(Data Segment):数据区包含两部分:
- 全局初始化数据区(Initialized Data Segment):存储全局变量和静态变量以及被显式初始化的变量。
- 全局未初始化数据区(Uninitialized Data Segment):也称为 BSS 区(Block Started by Symbol),存储未初始化的全局变量和静态变量,这些变量在程序开始执行之前会被系统初始化为零或空值。
-
堆区(Heap Segment):堆区是动态分配的内存区域,在程序运行时由程序员手动分配和释放。通过函数如
malloc()
、calloc()
、realloc()
来进行内存分配,通过free()
来释放已分配的内存。堆区通常在程序运行时动态增长和缩减。 -
栈区(Stack Segment):栈区用于存储函数的局部变量、函数参数、以及函数调用的返回地址等信息。栈是一种先进后出的数据结构,它的大小是固定的,由系统预先分配。栈区的内存分配和释放是由系统自动管理的,通过函数调用和返回来控制栈上数据的生命周期。
-
命令行参数和环境变量:这部分存储了程序运行时传递给它的命令行参数和环境变量。
调用fork函数后发生了什么?
-
创建子进程:操作系统会复制调用进程(父进程)的地址空间,包括代码段、数据段等。这样就创建了一个全新的子进程,但是它拥有与父进程完全相同的执行状态和代码。
-
分配新的进程ID:子进程会被分配一个新的进程ID,这个ID是操作系统为了标识进程而分配的唯一标识符。
-
父子进程返回:在父进程中,
fork()
返回子进程的进程ID,这个值是一个正整数,表示新创建的子进程的进程ID。而在子进程中,fork()
返回0,用于标识它是子进程。 -
执行后续代码:在父子进程中,
fork()
后面的代码会继续执行。由于父子进程在此时的状态完全相同,它们会从同一个地方继续执行代码。 -
并发执行:父子进程会并发执行各自的代码。它们是独立的进程,各自有自己的执行上下文和内存空间。因此,它们可以并行执行不同的任务。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid;
pid_t pid2;
pid_t retpid;
pid = getpid(); // 获取进程的唯一ID
printf("before fork : pid = %d\n", pid);
retpid = fork(); // fork函数创建一个子进程,返回两个值,在父进程返回子进程的ID
//在子进程返回0
pid2 = getpid(); // 父子进程分别获得各自的ID
if(retpid > 0){
printf("this is father print%d, retpid = %d\n", pid2, retpid);
}else{
printf("this is child print, child pid = %d, retpid = %d\n", pid2, retpid);
}
return 0;
}
结果:父进程和子进程的ID不同, 父进程的retpid是子进程的ID,子进程的retpid是0。