IO进程之进程笔记

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、程序与进程

程序:是一种静态的概念,表示有序指令的集合。

进程:是一种动态的概念,表示程序运行的过程(运行过程包含:创建、调度、消亡)

程序中包含:

1.数据段(全局、静态、部分常量...)

2.代码段(程序的指令)

进程中包含:

1.数据段(全局、静态、部分常量...)

2.代码段(程序的指令)

3.堆区、栈区

4.进程控制块(PCB):其实就是一个结构体   task_struct


二、进程状态

1.运行态

R:表示运行态  

+:前台运行

2.等待态

进程进入资源等过程,例如:getchar()等待终端输入

1.可中断(软件可中断):S 表示

2.不可中断(软件不可中断,但是硬件可以):D 表示这种状态一般表示与硬件正进行交互

3.停止态

T:表示停止,进程处于休眠的状态,需要通过特定信号将其唤醒

可以使用信号(Ctrl+Z)使进程进入停止态,同样gdb断点调试时也处于停止态(追踪模式)

4.僵尸态

Z:表示进程已经结束,但是资源没有回收完成

5.空闲状态

I :属于不可中断等待态D的内核线程,但是该内核线程可能实际上没有任何负载,该线程就是空闲状态


三、进程的系统调用

每一个进程都有自己的虚拟内存空间(32位系统为4G)

虚拟内存与物理内存有映射关系,但是虚拟内存的大小和物理内存的大小没有关系,与操作系统及CPU有关系

虚拟内存4G:1G内核内存   +   3G虚拟内存

与内核内存、物理内存

fork函数():

pid_t fork(void):  进程创建函数

{

  宏观角度:

该函数正确调用的话有两个返回值(区分父子进程):一个>0的值    一个==0的值

错误返回 -1

pid_t  p = fork();

if(p == -1):错误发生,常见错误原因:资源不足开辟不了进程

else if(p == 0):表示子进程(由于该子进程没有子进程,所以返回值为0)

else if(p > 0):表示父进程(其实就是子进程ID号,便于父进程管理子进程)

}

 fork()一旦被调用,则子进程会拷贝所有父进程的资源(正文段(fork之后的)、数据段、代码段、堆、栈...)

int main(int argc, char *argv[])
 10 {
 11     pid_t pid = fork();     //创建子进程
 12     if(pid == -1)
 13     {
 14         perror("fork error");
 15         exit(1);
 16     }
 17     else if(pid == 0)          //子进程
 18     {
 19      
 20     }
 21     else if(pid > 0 )          //父进程

循环fork():

int main()

{

        fork();

        fork();

        printf("hello\n");

}

for(i=0;i<2;i++)

{

        fork();

        printf("*\n");

}

打印多少个“*”号? 用二叉树的方法,寄存器中有"\n"则有6个,没有“”\n“”则有8个


四、进程资源回收

exit(0) //进程正常结束

exit(1) //进程异常结束

getpid():获取当前进程的ID号

 void exit(int status)

{
status:  结束状态

    EXIT_SUCCESS  或 0;代表正常结束

    EXIT_FAILURE   或 1 -1 :代表错误结束

要处理缓存区内容(比如:把缓存剩下的内容写入文件)

}

void _exit(int status)

{
status: 结束状态

     EXIT_SUCCESS 或 0:  代表正常结束   E

     EXIT_FAILURS  或  1  -1  代表错误结束

不对缓存做任何处理,直接退出进程

}

 资源回收函数:(子进程资源需要被父进程回收)

wait()与waitpid()

{

        等待子进程退出,并且回收子进程资源

    pid_t wait(int *status)

    status:获取进程退出状态           不需要的获取的话  就为NULL

    pid_t:返回子进程的进程号

    为了避免僵尸进程的出现,通常会用wait来回收子进程的资源

        pid_t waitpid(pid_t,int *status,int options)

        pid: pid > 0 只等待进程ID等于pid的子进程,不管其他已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去

        pid == -1 等待任何一个子进程退出,没有任何限制,此时waitpid和wait的作用一模一样

        pid == 0 等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬

ps axj 可以查看组进程

        pid < 0 等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值

        status: 与wait 一致

        options:为0 与wait函数一样,需要一直等待进程退出(阻塞)

        为WNOHANG 不需要等待(不阻塞)

返回值:正常返回子进程的进程号

使用选项WNOHANG且没有子进程结束时:0

错误:-1;

}


五、写时拷贝技术

原因:如果子进程完整拷贝父进程资源,但是并不会修改拷贝后的数据。只会使用,那就没有必要拷贝空间了,直接共享数据。

意义:当子进程或父进程需要修改数据时,才实现拷贝


六、exec函数族

exec函数族提供了一种在进程中启动另一个程序执行的方法。

新的可执行程序把子进程原来的数据段、代码段和堆栈段,全部替换,除了进程号外

int execl(const char *path,const char *arg,...)

int execv(const char *path,char *const argv[]);

int execle(const char *path,const char *arg,...,char *const envp[])

int execve(const char *path,char *const argv[],char *const envp[])

int execlp(const char *file,const char *arg,..)

int execvp(const char *file,char *const argv[])

l:  代表后面的参数的传入是 list 形式(依次传入)

v: 代表后面的参数的传入是以指针数组传入的。例如:char *arv[]= {"ls","-l",NULL};

p: 第一个参数不需要指明路径,只需要传入可执行文件名就可以了(在系统默认PATH路径下寻找)

e: 最后一个参数可以传入环境变量

除了第一个参数以外后面参数所有形式都需要以NULL结尾

例如:

char *arg[] = {"ls","-l",NULL}

execvp("ls",arg);

七、守护进程

1.创建进程,父进程退出(变成孤儿进程,由init进程继续管理,脱离父进程)

2.创建新会话(fork已经从父进程拷贝很多内容:会话期、进程组等...所以要完成脱离,就需要新的会话)setsid()

3.修改工作目录 chdir()(为了提升文件权限,使一般用户不能直接操作)

4.修改文件掩码。umask(0)(创建的文件不受掩码限制,变得更加灵活)

5.关闭文件描述符 close()  (0,1,2.对于守护进程没有作用,关闭可以节约资源)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值