系统编程--进程

进程是操作系统中的一个基本概念,它是正在执行的程序的实例。每个进程都有自己的地址空间程序代码、数据和堆栈。进程可以通过系统调用创建、销毁、等待和通信。

在系统编程中,进程通常是通过创建子进程来实现并发执行的。子进程可以通过调用 exec 系列函数来加载新的程序代码父进程可以通过 wait 系列函数来等待子进程的结束,并获取子进程的退出状态。

进程间通信可以通过管道、共享内存、消息队列、信号等方式实现。其中,管道是一种基于文件描述符的通信方式,共享内存和消息队列是基于内核对象的通信方式,信号是一种异步通信方式。

在子进程中打印自己与父进程的ID号(在子进程中调用getppid()),在父进程中打印自己与孩子的PID号(父进程中调用getpid()函数)。

示例:创建子进程

#include <unistd.h>
#include <stdio.h>

int main() {
    pid_t pid;
    pid = fork();
    if (pid == 0) {
        // 子进程代码
        printf("This is child process.\n");
    } else if (pid > 0) {
        // 父进程代码
        printf("This is parent process.\n");
    } else {
        // 创建进程失败
        perror("fork");
        return -1;
    }
    return 0;
}

等待子进程结束

#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>

int main() {
    pid_t pid;
    pid = fork();
    if (pid == 0) {
        // 子进程代码
        printf("This is child process.\n");
        return 0;
    } else if (pid > 0) {
        // 父进程代码
        printf("This is parent process.\n");
        int status;
        wait(&status);
        printf("Child process exit with status %d.\n", status);
    } else {
        // 创建进程失败
        perror("fork");
        return -1;
    }
    return 0;
}

exec函数
  fork的一个用法是创建一个新进程(子进程)然后调用某个exec函数然执行另一个程序。当一个进程调用某个exec函数时,这个进程被新程序完全取代,而新程序开始执行它的main函数。在调用exec时进程的ID并没有发生变化,因为没有一个新的进程被创建;exec只是把当前的进程--它的代码、数据、堆和栈--替换为从硬盘而来的全新的程序。
6个不同的exec函数

#include <unistd.h>
int execl(const char *pathname, const char *arg0, ... /* (char *) 0 */ );
int execv(const char *pathname, char * const argv[]);
int execle(const char *pathname, const char *arg0, ... /* (char *)0, char *const envp[] */ );
int execve(const char *pathname, char *const argv[], char *const envp[] );
int execlp(const char *filename, const char *arg0, ... /* (char *)0 */ );
int execvp(const char *filename, char *const argv[]);
//六个函数错误都返回-1,成功不返回。

使用示例:

使用v的,使用数组作为参数,第一个参数为程序本身
使用l的,使用参数列表,第一个参数为程序本身,最后一个参数为(char *)0
使用p的,可以使用环境变量中的程序,没有p的,必须使用绝对路径
execv
execl
execlp
execvp
char *const ps_argv[] ={"ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL};
char *const ps_envp[] ={"PATH=/bin:/usr/bin", "TERM=console", NULL};
execl("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
execv("/bin/ps", ps_argv);
execle("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL, ps_envp);
execve("/bin/ps", ps_argv, ps_envp);
execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
execvp("ps", ps_argv)

僵尸进程与孤儿进程:

孤儿进程是在失去父进程的时候马上寻找继父,祖先进程init就会成为该子进程的父进程,回收该子进程的资源。
 僵尸进程父进程还在,子进程先退出;但是子进程资源没有被回收,危险。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值