系统编程-------进程编程

多进程编程

1、进程的创建

1.1 复制创建新的进程

fork();

 #include <unistd.h>
 pid_t fork(void);

参数:

返回值: 成功,子进程的id号,返回给父进程,0返回给子进程;

​ 失败,返回-1给父进程,子进程不被创建

1.2替换创建新的进程

execl();家族函数

#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,..., char * const envp[]);

参数:

  • 第一个参数,指向被执行的文件,
  • 其余的参数以NULL作为结束标志。

返回值:成功不不返回参数,失败返回-1;

excev()家族函数

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

参数:

  • 第一个参数,指向被执行的文件,
  • 其余的参数以NULL作为结束标志。

返回值:成功不返回参数,失败返回-1

2、等待子进程的退出

wait;

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);

参数:进程状态

返回值:成功,返回退出子进程的ID值;失败返回-1;

waitpid();

#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);

参数:

  • 处理方式:

    <-1:等待任意子进程,其进程ID为pid绝对值

    -1:等待所有子进程

    0:等待任意组ID等于调用进程

    大于0:等待子进程ID等于pid的值

  • 进程状态

  • 选择值

返回值:成功返回0;失败返回-1;

3、进程间信号

信号处理函数signal

 #include <signal.h>
 typedef void (*sighandler_t)(int);
 sighandler_t signal(int signum, sighandler_t handler);

参数:

  • signum: 指定信号
  • handler:处理函数

返回值:成功,上一个信号值;失败,返回SIG_ERR

信号处理函数sigcation

#include <signal.h>
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
struct sigaction {
               void     (*sa_handler)(int);
               void     (*sa_sigaction)(int, siginfo_t *, void *);
               sigset_t   sa_mask;
               int        sa_flags;
               void     (*sa_restorer)(void);
           };

参数:

  • signum:指定信号
  • 非空,赋予新的信号
  • 非空,保存以前的信号

返回值:成功返回0;失败返回-1;

信号发送函数 kill();

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);

参数:

  • pid = 0;向组内所有进程发送信号
  • pid = -1;向允许发送的所有线程发送,不包含初始进程
  • pid < -1;向组内指定进程(-pid)发送信号

返回值:成功,返回0;失败,返回-1;

//信号实例
#include <stdio.h>
#include <signal.h>

void sig_handler(int signo);

int main(int argc, char *argv[])
{
    //typedef void (*sighandler_t)(int);
    //sighandler_t signal(int signum,
    //   sighandler_t handler);
    //signal(2, sig_handler);
    // 为指定信号注册信号处理函数
    signal(SIGINT, sig_handler);

    while(1);

    return 0;
}

void sig_handler(int signo)
{
    printf("hahahaha\n");
}

进程实例:

// 练习1:在父进程中为SIGINT信号注册处理函数,然后创建一个子进程,父子进程均进行无限循环,使用Ctrl+c组合键触发SIGINT信号,观察父子进程的执行情况
// 注意:子进程在创建时会copy当前父进程的信号处理方式
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void sig_handler(int signo);
int main(int argc, char *argv[])
{
    pid_t pid;
    struct sigaction act;//定义一个act访问sigaction结构体变量
    
    //signal(SIGINT, SIG_IGN);
    //signal(SIGINT, SIG_DFL);
    //signal(SIGINT, sig_handler);
    act.sa_handler = sig_handler;
    //act.sa_handler = SIG_IGN;
    //act.sa_handler = SIG_DFL;
    sigaction(SIGINT, &act, NULL);
    
    pid = fork();
    
    while(1);

    return 0;
}

void sig_handler(int signo)
{
    switch(signo)
    {
        case SIGINT:
            printf("signal SIGINT catched in process %d\n", getpid());
    }     
}
// 注意:本例使用信号异步处理僵尸进程
// 实现原理:当子进程退出时,会向父进程发送SIGCHLD信号,在父进程的SIGCHLD信号处理函数中调用wait函数,防止僵尸进程的产生

// 信号处理函数能够使用其形式参数接收触发该函数的信号值
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <stdlib.h>
void sig_handler(int signo);

int main(int argc, char *argv[])
{
    pid_t pid;

    srand(time(NULL));
    
    // sigaction
    signal(SIGCHLD, sig_handler);

    while(1)
    {
        pid = fork();
        if(pid == 0)
        {
            printf("child process %d is running...\n",  getpid());
            sleep(rand()%3+1); 
            
            //return 0;
            exit(0); 
        }
        else if(pid > 0)
        {
            sleep(1);
        }
    }

    return 0;
}

// 信号处理函数能够使用其形式参数接收触发该函数的信号值
void sig_handler(int signo)
{
    if(signo == SIGCHLD)
    {
        printf("child process %d is exit!!!\n",
            wait(NULL));
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Linux 进程管理与程序开发 进程是Linux事务管理的基本单元,所有的进程均拥有自己独立的处理环境和系统资源,...
    JamesPeng阅读 2,502评论 1 14
  • 一、进程的创建和调度 相关概念: 最基础的计算机动作被称为指令(instruction)。 程序(program)...
    穹蓝奥义阅读 4,714评论 0 6
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,859评论 18 139
  • 又来到了一个老生常谈的问题,应用层软件开发的程序员要不要了解和深入学习操作系统呢? 今天就这个问题开始,来谈谈操...
    tangsl阅读 4,163评论 0 23
  • 4月1日下午匆匆赶去孩子书院,一年多以来第一次和儿子一起吃住在书院,更加近的走进孩子的内心,小小的激动一下. 4月...
    杨俪颖阅读 513评论 0 0