首页 > 系统相关 >高编:进程(2)

高编:进程(2)

时间:2024-07-01 09:29:55浏览次数:3  
标签:status const int pid char 进程 高编

一、父子进程的关系:


    子进程是父进程的副本。子进程获得父进程数据段,堆,栈,正文段共享。
    
    在fork之后,一般情况那个会先运行,是不确定的。如果非要确定那个要先运行,需要IPC机制。
    
    区别:
    1)fork的返回值
    2)pid不同


二、进程的终止:8种情况


     正常终止
    1)main 中 return
    2)exit(), c库函数,会执行io库的清理工作,关闭所有的流(关闭所有的文件),以及所有打开的文件。已经清理函数(atexit)。

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 int main(int argc, const char *argv[])
  5 {
  6     printf("capper");                                                 
  7     exit(0);
  8     printf("made in future\n");
  9 
 10     return 0;
 11 }


    3)_exit,_Exit 会关闭所有的已经打开的文件,不执行清理函数。

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4                                                                         
  5 int main(int argc, const char *argv[])
  6 {
  7     printf("capper");
  8     _exit(0);
  9     printf("made in future\n");
 10 
 11     return 0;
 12 }


    4)  主线程退出
    5)主线程调用pthread_exit
    异常终止
    6)abort()(事态严重,内核调用)
    7)signal   kill pid (一般错误)
    8)  最后一个线程被pthread_cancle

    
    三、进程的退出


    僵尸进程(子先没)和孤儿进程(爹先没)
    
    僵尸进程:进程执行结束 但 空间未被回收 变成僵尸进程

1.exit     库函数


    退出状态,终止的进程会通知父进程,自己使如何终止的。如果是正常结束(终止),则由exit传入的参数。如果是异常终止,则有内核通知异常终止原因的状态。任何情况下,父进程都能使用wait,waitpid获得这个状态,以及资源的回收。
    void exit(int status) 
    exit(1);
    功能:
        让进程退出,并刷新缓存区 
    参数:
        status:进程退出的状态
    返回值:
        缺省
    
    EXIT_SUCCESS    0
    EXIT_FAILURE    1

    return  当该关键字出现在main函数中时候可以结束进程
            如果在其他函数中则表示结束该函数。
    exit -> 刷新缓存区 -> atexit注册的退出函数 -> _exit


    2._exit    系统调用


    void _exit(int status);
    功能:
        让进程退出,不刷新缓存区
    参数:
        status:进程退出状态
    返回值:
        缺省

    
             mian(int agc,argv)
{
    main();
}             


    3.atexit  回调函数


    int atexit(void (*function)(void));
    功能:
        注册进程退出前执行的函数
    参数:
        function:函数指针
            指向void返回值void参数的函数指针
    返回值:
        成功返回0
        失败返回非0

    当程序调用exit或者由main函数执行return时,所有用atexit
    注册的退出函数,将会由注册时顺序倒序被调用

四、进程空间的回收
  

exit(20);
    

1.wait

    pid_t wait(int *status);
    
功能:该函数可以阻塞等待任意子进程退出
      并回收该进程的状态。
      一般用于父进程回收子进程状态。

参数:status 进程退出时候的状态
      如果不关心其退出状态一般用NULL表示
      如果要回收进程退出状态,则用WEXITSTATUS回收。

返回值:成功 回收的子进程pid
              失败 -1;
 

WIFEXITED(status)  子进程是不是正常结束,(必须是正常结束)

WEXITSTATUS(status) 使用这个宏去那返回值,

WIFSIGNALED(status) 是不是收到了信号而终止的       

WTERMSIG(status)如果是信号终止的,那么是几号信号。

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 #include <string.h>
  5 #include <sys/types.h>
  6 #include <sys/wait.h>
  7 
  8 int main(int argc, char *argv[])
  9 {
 10     pid_t pid = fork();
 11     if(pid>0)
 12     {
 13         int status;
 14         printf("father pid:%d ppid:%d\n",getpid(),getppid());
 15         pid_t recycle_pid = wait(&status);
 16         if(WIFEXITED(status))
 17         {
 18 
 19         printf("child normal terminal,recycle pid %d , exit value %d\n"
 20                ,recycle_pid,WEXITSTATUS(status));
 21         }
 22         if(WIFSIGNALED(status))
 23         {
 24             printf("child terminal bu signal ,rrecycle pid %d, signal num %d \n"
 25                    ,recycle_pid,WTERMSIG(status));
 26         }
 27     }
 28     else if(0 == pid)
 29     {
 30         printf("child pid:%d ppid:%d\n",getpid(),getppid());
 31         sleep(5);
 32         exit(20);
 33     }
 34     else
 35     {
 36         perror("fork");
 37         return 1;
 38     }                                                                                                                                                                                                                                                             
 39 
 40     return 0;
 41 }

2.waitpid

 
    waitpid(-1,status,0)=wait(status);
    pid_t waitpid(pid_t pid, int *status, int options);

   < -1 回收指定进程组内的任意子进程
    -1 回收任意子进程,组内外
    0 回收和当前调用waitpid一个组的所有子进程,组内
    > 0 回收指定ID的子进程
     waitpid (-1,a,0)  == wait(a);
     status 子进程退出时候的状态,
                如果不关注退出状态用NULL;
      options 选项:
                  0  表示回收过程会阻塞等待
                  WNOHANG 表示非阻塞模式回收资源。
    返回值:成功 返回接收资源的子进程pid
                  失败  -1
                            0,

3.exec

execute
exec族(有6个,功能一样,参数不一样)
用fork创建子进程后 执行的是 和父进程相同的程序(但有可能执行不同的代码分支),
子进程往往要调用一种 exec函数 以执行另一个程序。当进程调用一种exec函数时,
该进程的用户空间代码 和 数据 完全被新程序(data段,code段都替换) 替换,从新程序的启动例程开始执行。
调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。
有六种以exec开头的函数,统称exec函数:
vector
ls -l -i list 
execl("/bin/ls","-l","-i",NULL);
execlp("ls","-l","-i",NULL);
#include <unistd.h>
int execl(const char *path, const char *arg, ...);

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 
  4 int main(int argc, const char *argv[])
  5 {
  6     execl("/usr/bin/firefox","firefox","www.taobao.com",NULL);
  7     printf("看见就错了\n");                                       
  8 
  9     return 0;
 10 }

 运行结果:成功打开火狐淘宝页面


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

key=value
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execle(const char *path, const char *arg, ..., char *const envp[]);

int execve(const char*path,char*const argv[],char*const evnp[]);
int execlp(const char *file, const char *arg, ...);

p:env $PATH 有一堆路径,里面有bin,ls 在bin路径下,即不需要/bin/ls,直接ls即可

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 
  4 int main(int argc, const char *argv[])
  5 {
  6     //ls -a -l -h -F
  7 //  execl("/bin/ls","ls","-a","-l","-h","-F",NULL);
  8     //env path
  9     execlp("ls","ls","-a","-l","-h","-F","--color",NULL);
 10     
 11     printf("看见就错了\n");
 12     return 0;                                                               
 13 }   

echo $PATH
PATH= (bin在里面)


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

这些函数的区别
    1),前4个使用路径名作为参数,后面两个使用文件名做参数
    当filename中,含有/时视为路径名,否则就按PATH变量,在指定目录下查找可执行文件。
    2)相关的参数表传递
    l表示list,v表示vector
    execl,execlp,execle,需要将参数一个一个列出,并以NULL结尾。
    execv,execvp,execve,需要构造一个参数指针数组,然后将数组的地址传入。

    3)以e结尾的函数,可以传入一个指向环境字符串的指针数组的指针。其他未指定环境变量,使用父进程继承过来的。
execve 是真正的系统调用
这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回,如果调用出错
则返回-1,所以exec函数只有出错的返回值而没有成功的返回值。


综合练习:execl、execlp、execv、execvp 调用可执行文件argc

1)有 p ,加上 ./ 在当前路径查找,没有 p 不需要 ./

2)execl、execlp 第一个参数放可执行文件,NULL前的参数 放 传到可执行文件argc的参数

3)execv、execvp 函数里放可执行文件、数组名;数组放传到可执行文件argc参数

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 
  4 int main(int argc, char *argv[])
  5 {
  6     execl("argc","0","1","2",NULL);                                                   
  7 
  8 //  execlp("/home/linux/yxy/stdio/system/jincheng/sec2/argc","0","1","2",NULL);
  9 //  execlp("./argc","0","1","2",NULL);
 10 
 11 //  char *const arg[] = {"0","1","2",NULL};
 12 //  execv("argc",arg);
 13 
 14 //  char *const arg[] = {"0","1","2",NULL};
 15 //  execvp("./argc",arg);
 16 
 17     printf("看见就错了\n");
 18     return 0;
 19 }

标签:status,const,int,pid,char,进程,高编
From: https://blog.csdn.net/weixin_71751116/article/details/139992210

相关文章

  • Linux进程间的通信方式(一)System V 消息队列
    文章目录前言1.消息队列概念2.消息队列的应用场景3.消息队列接口分类3.1SystemV消息队列3.2POSIX消息队列4.消息队列相关操作函数4.1ftok函数(获取一个key值)4.2msgget函数(根据key值获取一个消息队列操作符)4.3msgctl函数(设置消息队列属性)4.4msgsnd函......
  • 【使用sudo apt-get出现报错】——无法获得锁 /var/lib/dpkg/lock-open(11:资 源暂时
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、ubuntu中进程正在被占用1.问题描述2.原因分析3.解决总结前言一、ubuntu中进程正在被占用1.问题描述在Ubuntu中,使用终端时输入带有sudoapt-get指令更新软件包时,出现如下的报......
  • 超详细Python教程—— 进程
    进程Python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在Python中大部分情况需要使用多进程。Python提供了非常好用的多进程包multiprocessing,只需要定义一个函数,Python会完成其他所有事情。借助这个包,可以轻松完成从单进程到并发执行的转......
  • Batch文件中使用tasklist命令:深入掌握进程监控与分析
    在Windows操作系统中,tasklist命令是一个强大的工具,它允许用户查看当前运行的进程和它们的详细信息。在自动化脚本和批处理文件(Batch文件)中使用tasklist可以极大地增强对系统状态的监控能力。本文将详细介绍如何在Batch文件中使用tasklist命令来查看和管理进程。1.tasklist......
  • 线程进程以及多线程多进程(超详解)
    目录前言一、什么是进程和线程进程(Process)线程(Thread)多线程(Multithreading)多进程(Multiprocessing)相互组合关系二、资源分配进程私有资源共享资源线程私有资源共享资源多进程私有资源共享资源多线程私有资源共享资源进程的共享和私有资源线......
  • Linux 7种 进程间通信方式
    传统进程间通信       通过文件实现进程间通信必须人为保证先后顺序       A--->硬盘--->B(B不知道A什么时候把内容传到硬盘中)1.无名管道2.有名管道3.信号IPC进程间通信4.消息队列5.共享内存6.信号灯集7.socket通信一、无名管道(亲缘关系的进程  ......
  • 【Linux】进程间通信_1
    文章目录七、进程间通信1.进程间通信分类管道未完待续七、进程间通信进程间由于进程具有独立性,所以不可以直接进行数据传递。但是我们通常需要多个进程协同,共同完成一件事,所以我们需要进程间通信的手段。进程间通信的本质就是先让不同的进程看到同一份资源,这个......
  • Linux的学习与使用(进程管理)
    命令学习(一)ps命令1.ps显示当前终端会话的进程。2.psaux显示系统上所有进程的详细信息。NameDescriptionExample(图中第一行)USER进程的所有者rootPID进程ID1%CPU进程占用的CPU百分比0.2%MEM进程占用的内存百分比0.2VSZ进程使用的虚拟内存量......
  • 进程切换分析(2):TLB处理
    一、前言进程切换是一个复杂的过程,本文不准备详细描述整个进程切换的方方面面,而是关注进程切换中一个小小的知识点:TLB的处理。为了能够讲清楚这个问题,我们在第二章描述在单CPU场景下一些和TLB相关的细节,第三章推进到多核场景,至此,理论部分结束。在第二章和第三章,我们从基本的逻辑......
  • 操作系统的发展史、多道技术、进程理论、进程的三状态、同步异步/阻塞与非阻塞、开启
    【操作系统发展史】1为什么要使用操作系统呢?2程序员无法把所有的硬件操作细节都了解到,管理这些硬件并且加以优化使用是非常繁琐的工作,3这个繁琐的工作就是操作系统来干的,有了他,程序员就从这些繁琐的工作中解脱了出来,4只需要考虑自己的应用软件的编写就可以了,应用软件......