目录
目录
1.进程概念
1.1 进程的基本概念
代码 -- 程序员写出来字符文件 -- 磁盘中
程序 -- 将字符文件编译得到的二进制文件 -- 磁盘中
进程 -- 正在运行的程序/程序被加载到内存中 -- 内存中
同一个程序,多次加载到内存中,产生的是不同的进程。
1.2 查看进程
LInux系统下:ps - ef ps -aux
1.3 进程的特点
动态性:进程的实质是程序的一次执行过程,进程是动态产生,动态消亡的。
并发性:任何进程都可以同其他进程一起并发执行。
独立性: 进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位。
异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的,不可预知的速度向前推进。
1.4 进程的资源分配
计算机给每一个进程都会分配4G的虚拟内存:
分为4个部分:
堆区:-- 需要手动开辟,手动释放
栈区:-- 局部变量
数据段:-- 全局区、静态区
代码段:-- 代码 常量区
1.5 进程的状态
执行态:当下正在占用CPU,cpu划分时间片
就绪态:已经做好了可以执行的一切准备,等待cpu划分时间片
等待态:等待某事件发生
1.6 进程管理
暂停 恢复 杀死进程
Linux:
指令:ps - ef
ps - aux 获取PID号
ctrl + c ctrl + \
kill -9 PID 给PID这个进程发送9信号,9信号专门用来杀死进程
1.7 进程间关系
父子关系
父进程:该进程是由谁引导产生的,谁就是该进程的父进程;
1.8 创建进程
1:运行一个可执行程序
2:在程序中使用函数,可以创建进程 fork vfork
2、进程相关API函数
2.进程相关函数
2.1 获取进程 pid --getpid
头文件:
#include <sys/types.h>
#include <unistd.h>
函数原型:
pid_t getpid(void);//获取当前进程的进程号
形参: 无
返回值: pid_t 类型的 pid 号
pid_t getppid(void);//获取当前进程的父进程的进程号
形参: 无
返回值: 当前进程的父进程的进程号
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc,char*argv[])
{
pid_t pid=getpid();
pid_t ppid=getpid();
printf("pid=%d,ppid=%d\n",pid,ppid);
while (1)
{
}
return 0;
}
2.2 结束进程
1.在main函数中运行return,可以结束进程(return的功能是退出当前函数)
2.exit(0);//结束进程,结束之前可以刷新缓冲区。
头文件:
#include <stdlib.h>
函数原型:
void exit(int status);
形参:status:进程退出时的状态,一般写0;
返回值:无
3 _exit(0);//结束进程,结束之前不刷新缓存区
插入:
sleep函数
头文件:
#include <unistd.h>
函数原型:
unsigned int sleep(unsigned int seconds);
形参: seconds 秒数
功能: 阻塞性, 在该函数的位置, 延时 seconds 秒之后, 解除阻塞
sleep(1); : 代码在该位置阻塞 1 秒, 1 秒之后往下继续运行
2.3 fork -- 创建子进程
头文件:
#include <sys/types.h>
#include <unistd.h>
函数原型:
pid_t fork(void)
形参:无
返回值:在父进程中返回子进程的PID号(>0的值)
在子进程中,返回0;
失败返回-1;
解释:进程中运行到fork的时候,我们就有两个进程,原本的通过./a.out产生的父进程,通过fork产生的是子进程
fork 创建的子进程的特点:
1.子进程复制父进程的所有资源(堆区,栈区,数据段,代码段),父子进程相互独立,互不干扰;
2.子进程从fork的下一行开始运行;
3.父子进程并发运行,谁先谁后看cpu调度
特殊进程介绍:
父子进程: 父进程拥有子进程的 PID 号;
0 号进程: 操作系统的引导程序
1 号进程/祖先进程: 操作系统运行起来的第一个进程
孤儿进程: 父进程已经结束, 子进程还在运行, 此时就产生孤儿进程, 孤儿进程会被
收养,进程退出之后帮其收尸
僵尸进程: 子进程退出了, 但是父进程太忙了, 没空帮其回收资源, 僵尸进程时一种几乎放弃了所有资源, 但是占用一个进程号!
s-睡眠 r-运行 z-僵尸
2.4 进程等待函数
1.等待任意子进程退出 -- wait
阻塞性函数:等待任意子进程退出,只有子进程退出了,该函数才能解除阻塞!
头文件:
#include <sys/types.h>
#include <sys/wait.h>
函数原型:
pid_t wait(int *wstatus);
形参:wstatus -- 保存进程退出时的状态,一般写NULL
返回值:成功返回为其收尸的子进程的进程号;
2.等待指定子进程退出
头文件:
#include <sys/types.h>
#include <sys/wait.h>
函数原型:
pid_t waitpid(pid_t pid,int *wstatus,int options);
形参:pid -- 你要等待哪一个子进程退出
可以写-1,表示等待任意子进程退出(类似于wait!)
wstatus:NULL;
options : 填0,阻塞等待子进程退出,(类似于wait)
填WNOHANG,不阻塞如果子进程刚好退出,帮其收尸,没退出,不阻塞,直接就过去了,运行下一行代码;
返回值:
如果option填0,返回为其收尸的子进程的进程号;
如果 options 填WNOHANG,如果子进程刚好退出,帮其收尸,返回为其收尸的子进程的进程号,如果子进程没有退出,不阻塞,直接返回0;
waitpid(-1,NULL,0); == wait(NULL);
2.5 Vfork -- 创建子进程函数
头文件:
#include <sys/types.h>
#include <unistd.h>
函数原型:
pid_t vfork(void);
形参:无
返回值:在父进程中返回子进程的PID号
在子进程中返回0
特点:子进程先运行,运行结束,父进程才能运行
子进程和父进程共享资源
单独使用vfork函数会出现段错误
解决段错误:
方式1:子进程中必须有exit(0);
方式2:结合exec
3. system函数
功能:在当前进程中运行其他进程
头文件:
#include<stdio.h>
函数原型:
int system(const char *command);
形参:command:新的进程的启动命令
如果是自己写的可执行程序,填写绝对路径+可执行程序名
举例:名为:main 在/home/yym/路径中,要写绝对路径:
system(“/home/yym/main”);
如果是系统提供的:不同加路径
举例:system("ls-l -a -i");
4 exec 函数族
往往和fork/vfork配合使用
在当前进程中启动另一个进程,当前的进程空间完全被取代,仅仅保留了原本的PID号
头文件:
#include <unistd.h>
函数原型:int execl(const char *pathname, const char *arg, .../* (char *) NULL */);形参:pathname -- 新的可执行程序的路劲+可执行程序名,必须是绝对路径
arg:可变传参,可以有1个或者多个
arg1 -- 填可执行程序名
arg2 -- 给可执行程序传递的参数
最后必须以NULL结束
int execlp(const char *file, const char *arg, .../* (char *) NULL */);
形参: file 新的可执行程序的程序名,如果是自己的,写绝对路径;
如果是系统的直接写可执行程序名即可
arg: 可变传参, 可以有 1 个或者多个
arg1 -- 填可执行程序名
arg2 -- 给可执行程序传递的参数
。 。 。
最后必须以 NULL 结尾
int execv(const char *pathname, char *const argv[]);
形参: pathname -- 新的可执行程序的路径+可执行程序名
必须是绝对路径(不管是自己的还是系统的 ls/clear 等等)
argv: 指针数组, 直接看如下举例
将 execl("/bin/ls","ls","-l","-a",NULL);改为 execv, 如下:
char *argv[] = {"ls","-l","-a",NULL};
execv("/bin/ls",argv)
int execvp(const char *file, char *const argv[]);
形参: file 新的可执行程序的程序名,如果是自己的,写绝对路径;
如果是系统的直接写可执行程序名即可
argv: 指针数组, 直接看如下举例
将 execlp("ls","ls","-l","-a",NULL);改为 execv, 如下:
char *argv[] = {"ls","-l","-a",NULL};
execvp("ls",argv);
vfork特点:
子进程没有自己的空间,和父进程共用空间,子进程先运行,退出之后父进程才能运行vfork+exec 函数结合的特点:
子进程将被分配空间, 不再和父进程共享空间, 父子进程并发运行
fork+exec 函数结合的特点:
父子进程并发运行
父子进程空间各自独立
插入补充说明:
_LINE_ 就是当前的行号 %d
_FUNCTION_ 就是当前的函数名 %s
_FILE_ 就是当前的文件名 %s
printf("行:%d\n", _LINE_ );
printf("文件名:%s\n", _FILE_ );
printf("函数名:%s\n", _FUNCTION_ );