linux ——process
1、概念
进程是具有独立功能的程序关于某个数据集合的一次运行活动,是系统进行资源管理的基本单位。
(程序是存放在存储介质上的静态指令的集合,与进程最大的区别,程序是静态的,进程是动态的)
2、用途
进程是管理事务的基本单元:操作系统是通过进程去完成某个任务,管理事务,就好像,学校是通过班级管理事情,公司是通过部门去管理
3、特点
进程就运行的状态可分为三种状态,就绪态、运行态、阻塞态。
运行态<==>就绪态<---阻塞态<----运行态
4、用法
①创建进程
#include <unistd.h>
pid_t fork(void);
pid_t vfork(void);
fork与vfork的区别与共同点:
区别:
①fork创建的进程父、子进程运行顺序不确定,而vfork创建的进程保证子进程先运行,子进程结束(调用exit或exec)运行父进程再运行
②fork创建的子进程完全是父进程的一个复制品,它从父进程处继承了整个地址空间,而vfork在调用exec或exit之前,它在父进程的地址空间运行,在exec之后子进程会有自己的进程空间
③vork可以实现父子进程之间简单的同步
共同点:
都可以创建一个新进程
②进程的资源回收
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
等待子进程改变状态,如果子进程终止了,此函数会回收子进程的资源。调用wait函数的进程会挂起,直到它的一个子进程退出或受到一个不能被忽视的信号时才被唤醒。
执行成功返回子进程的pid号,出错返回-1.
pid_t waitpid(pid_t pid,int *status,int options);
等待子进程改变状态,如果子进程终止了,此函数会回收子进程的资源。
pid>0 等待进程id等于pid的子进程;
pid=-1;等待任一子进程,此时waitpid和wait作用一样
pid<-1 等待指定进程组中的任何子进程,这个进程组的id等于pid的绝对值。
③进程的关闭
#include <stdlib.h>
void exit(int status);
exit函数:结束进程执行
#include <unistd.h>
void exit(int value)
参数:
status:返回给父进程的参数(低8位有效)。
_exit函数:结束进程执行
#include <unistd.h>
void _exit(int value)
参数:
status:返回给父进程的参数(低8位有效)。
exec函数族,是由六个exec函数组成的。
exec函数族提供了六种在进程中启动另一个程序的方法。
exec函数族可以根据指定的文件名或目录名找到可执行文件。
调用exec函数的进程并不创建新的进程,故调用exec前后,进程的进程号并不会改变,其执行的程序完全由新的程序替换,而新程序则从其main函数开始执行。
#include <unistd.h>
int execl(const char *pathname, const char *arg0,…,NULL);
int execlp(const char *filename, const char *arg0,…,NULL);
int execle(const char *pathname, const char *arg0,…,NULL, char *const envp[]);
int execv(const char *pathname, char *const argv[]);
int execvp(const char *filename, char *const argv[]);
int execve(const char *pathname, char *const argv[], char *const envp[]);
六个exec函数中只有execve是真正意义的系统调用(内核提供的接口),其它函数都是在此基础上经过封装的库函数。
l(list):
参数地址列表,以空指针结尾。
参数地址列表
char *arg0, char *arg1, ..., char *argn, NULL
v(vector):
存有各参数地址的指针数组的地址。
使用时先构造一个指针数组,指针数组存各参数的地址,然后将该指针数组地址作为函数的参数。
p(path)
按PATH环境变量指定的目录搜索可执行文件。
以p结尾的exec函数取文件名做为参数。当指定filename作为参数时,若filename中包含/,则将其视为路径名,并直接到指定的路径中执行程序。
e(environment):
存有环境变量字符串地址的指针数组的地址。execle和execve改变的是exec启动的程序的环境变量(新的环境变量完全由environment指定),其他四个函数启动的程序则使用默认系统环境变量。
5、案例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
void shell(void)
{
while(1)
{
char cmd_buf[200] = "";
char *argv[20] = {NULL};
int i = 0;
getcwd(cmd_buf, sizeof(cmd_buf));//获取当前目录保存在字符数组当中。
printf("[%s@ %s]$", getenv("USER"), 1+strrchr(cmd_buf, '/'));//打印提示符号。
fgets(cmd_buf, sizeof(cmd_buf), stdin);//获取字符串
cmd_buf[strlen(cmd_buf)-1] = '\0'; //把最后一位'\n'变成字符串结束标志'\0'
if(cmd_buf[0] == '\0')
continue; //如果是输入回车的话,继续while循环
argv[i] = cmd_buf;
while((argv[i++]=strtok(argv[i]," "))!=NULL); //字符串按空格切割
if(fork()==0) //创建子进程 调用execvp运行外部命令。
{
printf("argv[0] = %s\n", argv[0]);
execvp(argv[0],argv);
printf("command no found!\n");
exit(1);
}
wait(NULL); //父进程等待子进程结束。
}
}
int main(int argc, char *argv[])
{
shell();
return 0;
}