学习Linux新手、入门小白必看的Linux环境下编程基础

进程与程序:

程序就是存储在磁盘上包含可执行指令、数据的静态实体。
进程就被操作系统读取加载到内存中的正在执行的程序。

进程的分类:

守护进程:由系统在开机时通过启动脚本激活的,总处理活动状态,一般运行在后台维护系统的正常运行,进程号为1的init。
批处理进程:系统会每隔一段时间集中处理该类进程的相关指令,会有定的延时,但避免的状态切换的耗时因此执行效率高。
交互进程:在执行需要用户输入一些数据否则无法继续执行。

Linux/UNIX系统查看进程:

简单形式:ps 以简略方式显示当用户当前终端有控制权的进程。
详细显示:ps aux
    a 所有用户的当前终端有控制权的进程
    u 显示详细信息
    x 包含无控制权进程
进程的信息列表:
    USER 进程属主
    PID 进程IP
    %CPU CPU使用率
    %MEM 内存使用率
    VSZ 使用虚拟内存的大小(KB)
    RSS 使用物理内存的大小(KB)
    TTY 终端设备号,?表示无终端控制
    STAT 进程的状态
        O 就绪态,所有准备工作都已经完成,等待被系统执行。
        R 运行状态的进程,Linux系统中没有就绪态,就绪态也用R表示。
        S 可被唤醒的睡眠,当收到系统中断、获取到资源、收到信号都可以抟进程唤醒转入运行状态。
        D 不可以唤醒的睡眠,只能被系统调用wake_up唤醒。
        T 暂停,收到信号SIGSTOP进程将转为暂停状态,收到SIGCONT信号转为进行状态。
        Z 僵尸状态,进程已经结束运行,但其父进程还没有回收它的资源。
        s 会话首进程
        l 多线程进程
        < 高优先级进程
        N 低优先级进程
        + 前台进程    
    START 进程启动时间
    TIME 进程的运行时间
    COMMAND 启动进程的程序

父进程与子进程:

1、一个进程可以创建另一个进程,创建者叫父进程,被创建者叫子进程。
2、父进程启动子进程后,子进程会在操作系统的高度下与父进程同时执行。
3、子进程先于父进程结束时,会向父进程发送SIGCHLD信号,父进程收到SIGCHLD信号后就应该去回收子进程的相关资源,如果父进程没有及时回收子进程将变成僵尸进程。
4、父进程先子进程结束,子进程就会变成孤儿进程,同时会被init进程收养,即成为init的子进程,而init进程也叫孤独院。

进程标识符:
1、每个进程都会有一个以非负数表示的唯一的标识,也就是进程ID,相当于进程的身份证号。
2、进程在任何时候都是唯一的,但可以重用,当一个进程结束时,它的进程ID就可以被其它进程使用(延迟重用)。

pid_t getpid(void);
功能:获取当前进程的进程ID。

pid_t getppid(void);
功能:获取当前进程的父进程ID。

fork创建进程:

pid_t fork(void);
功能:创建一个子进程
返回值:
    失败返回一次 -1
    成功返回两次,子进程返回0,父进程返回子进程ID。

1、通过fork创建的子进程会拷贝父进程的代码段、全局数据段、静态数据段、堆、栈、IO流缓冲区、文件表。
2、进程创建完成后,父子进程各自独立运行,先后顺序不确定。
3、当进程的总数超出系统限制,fork将创建失败。
4、通过fork创建的子进程会继承父进程的信号处理方式。

vfork创建进程:

pid_t vfork(void);
功能:创建子进程
返回值:
    失败返回一次 -1
    成功返回两次,子进程返回0,父进程返回子进程ID。

区别:
vfok创建的子进程不会复制父进程的代码段资源,而是通过exec系列函数直接加载一个可执行文件启动子进程。
子进程创建成功前,子进行暂时借用父进程的相关资源来加载子进程,而此时的父是阻塞状态,只有子进程创建成功后,父进程才继续运行。
通过vfork创建的子进程,不会继承父进程的信号处理方式。

int execl(const char *path, const char *arg, ...);
path:可执行文件的路径
arg:命令行参数,至少一个,且以NULL结尾。

int execlp(const char *file, const char *arg, ...);
file:可以执行文件名,该文件必须存储在PATH环境变量的路径下。
arg:命令行参数,至少一个,且以NULL结尾。

int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
argv:存储命令行参数的字符串数组,最后一个必须是NULL。

system创建进程:

int system(const char *command);
功能:加载一个可执行程序创建子进程
返回值:成功返回0,失败返回-1。
区别:子进程执行时,父进程阻塞,子进程执行结束后父进程才继续。

进程的正常退出:
1、从main函数return

2、调用标准C函数exit
无论在任何时候的任何位置调用此函数的进程会立即结束。

void exit(int status);
功能:结束当前进程,一旦执行就不会返回。
status:进程的结束状态码,与main函数中的返回值具有同样的意义,反映了进程是如何结束的,父进程调用相关函数可以获取status的你8位,常用的参数:EXIT_SUCCESS,EXIT_FAILURE。

进程在结束之前会执行atexit/on_exit注册的函数,然后再调用_exit/_Exit函数。

 int on_exit(void (*function)(int , void *), void *arg);
        int atexit(void (*function)(void));
        功能:向内存注册一个函数,进程结束时自动执行被注册的函数。
        void (*function)(int , void *)
        int:exit函数的参数或者return的返回值
        void*:是on_exit注册时的第二个参数 

3、调用_exit/_Exit函数
    void _exit(int status);
    功能:Linux系统提供的进程结束函数

    void _Exit(int status);
    功能:标准库提供的等价于_exit的进程结束函数,目的是为了提高代码的兼容性。
    
    1、status可以是exit函数的参数,也可以是用户提供的,父进程调用相关函数可以获取status的你8位。

    2、冲刷所有文件的缓冲区,关闭所有文件。

    3、把子进程托付给init进程收养。

    4、向父进程发送SIGCHLD信号。

4、进程的最后一个线程执行了返回语句。

5、进程的最后一个线程调用了pthread_exit函数。

进程的异常中止:

1、进程接收到某些信号(他杀)。
2、调用abort函数(自杀)。
3、最后一个线程对取"消请"求做出响应。

回收子进程:

pid_t wait(int *status);
功能:等待所有子进程结束,回收子进程,如果所有子进程都在运行,父进程阻塞。
返回值:
 如果没有子进程则返回错误ECHILD。
 只要有一个子进程结束,则返回子进程的进程ID和结束状态码。
    
pid_t waitpid(pid_t pid, int *status, int options);
功能:等待指定的子进程结束,回收子进程。
pid:
    < -1 等待进程组号为abs(pid)的进程结束。
    = -1 等待任意子进程结束
    = 0 等待组进程ID为当前进程ID的进程结束。
    > 0 等待进程ID为pid的进程结束。
options:
    WNOHANG 如果没有子进程则立即返回。
    WUNTRACED 子进程停止立即返回。
    WCONTINUED 子进程由暂停状态转为继续状态也返回。
返回值:
    如果没有子进程则返回错误ECHILD。
    等待的进程结束,则返回进程ID和结束状态码。

解析status的宏:

    WIFEXITED(status) 检查进程是否正常退出。
    WEXITSTATUS(status) 获取status的低八位,但只有WIFEXITED(status)结果为真时才有意义。
    WIFSIGNALED(status) 检查进程是否被信号中止。
    WTERMSIG(status) 获取导致进程中的信号,WIFSIGNALED(status)结果为真时才有意义。
    WCOREDUMP(status) 检查进程是否由于核心转储结束(段错误),WIFSIGNALED(status)结果为真时才有意义。
    WIFSTOPPED(status) 检查进程是否处理暂停状态,WIFSIGNALED(status)结果为真时才有意义。
    WSTOPSIG(status) 获取导入进程暂停的信号,WIFSTOPPED(status)结果为真才有意义。
    WIFCONTINUED(status) 当进程由暂停转换为继续运行进返回真。

当父进程收到子进程的SIGCHLD信号时,就应该调用wait/waitpid函数回收子进程。
如果子进程已经结束,在调用wait/waitpid函数之前子进程处于僵尸状态,调用后子进程会立即消息。
如果不关心子进程的结束状态,status的参数可以为NULL。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值