Linux进程间通信

进程基本知识

  1. 进程标识符 pid
类型pid_t
命令ps
ps axf
ps axm
ps ax -L
进程号是顺次向下使用(fd是使用最小的fd)
getpid();
getppid();

  1. 进程的产生

复制进程并创建进程,执行1次,返回2次
fork()
注意理解关键字:duplicating,意味着拷贝,克隆,一模一样等含义。
fork后父子进程的区别:fork的返回值不一样,pid不同,ppid也不同,未决信号和文件锁不继承,资源利用量清0
init进程:1号,是所有进程的祖先进程
调度器的调度策略来决定哪个进程先运行

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


int main()
{
    pid_t pid;
    printf("[%d]Begin!\n",getpid());
//非常重要 ,输出设备默认是行缓冲区,所以会默认fflush。但是重定向文件./fork >/tmp/out是全缓冲模式 ,父子进程都有begin所以打印两次 .fork之前必须fflush
fflush(NULL);
    //pid =0表示子进程 pid>0表示父进程
    pid = fork();
    if(pid<0)
    {
        perror("fork()");
    }
    if(pid==0)
    {
        printf("[%d]:Child is working!",getpid());
    }
    else
    {
        printf("[%d]:Parent is working!",getpid());
    }
    printf("End");
        //getchar();
    exit(0);
}

有可能是父进程先调度或者子进程先被调度


输出结果:

如果我们把输出现在在重定向文件上,则会出现两次的begin。这是因为输出设备默认是行缓冲区,所以会默认fflush。但是重定向文件./fork >/tmp/out是全缓冲模式 ,父子进程都有begin所以打印两次,且子进程也是打印父进程的pid .fork之前必须fflush

  • fork出的子进程和父进程都对应同一个内存数据对象。谁如果要对该数据对象进行写的操作,就自己复制一个内存数据对象,称为写时拷贝,谁写谁拷贝,然后影响的只是自己进程所指向的对象。
  1. 进程的消亡及释放资源
    wait(int *status) 等待进程状态发生变化
    waitpid(pid_t pid,int *status,int options)
    waitid()
    wait3()
    wait4()
  2. exec函数族 当执行这个函数的时候,该函数族执行的二进制文件将替换原有的进程,原有进程的内容都不执行,而是执行exec里的内容。
    execl();
    execlp();
    execle();
    execv();
    execvp();
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    pid_t pid;
    puts("Begin!");
    fflush(NULL);
    fork();
    if(pid<0)
    {
        perror("fork()");
        exit(1);
    }
    if(pid==0)
    {
        //子进程返回0,父进程返回子进程的pid
        execl("/bin/date","date","+%s",NULL);
        //如果子进程执行execl失败则会继续执行下面的代码
        perror("execl");
        exit(1);
    }
    //父进程等待子进程返回,替他收尸
    wait(NULL);
    puts("End!");
    exit(0);
}

注意:在执行exec函数族之前,也必须先执行fflush(NULL)函数进行刷新缓冲区。


image.png
  1. 用户权限及组权限
    setid()
    setreuid()
    setregid()
    seteuid()
    setegid()
  2. 观摩课:解释器文件
  3. system();
  4. 进程会计
    acct()
  5. 进程时间
    times()
  6. 守护进程
    查看进程命令:ps -axj
    一般指系统开机就会自动运行的进程。守护进程的父进程即ppid=1,pid=pgid=sid
    会话session,标识sid
    终端
    setsid() //创建守护进程
    getpgrp()
    getpgid()
    setpgid()
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FNAME "/tmp/out"

//守护进程例子
static int daemonize(void)
{
    int fd;
    pid_t pid;
    pid = fork();
    if(pid<0)
    {
        perror("fork()");
        return -1;
    }
    if(pid>0)
    {
        exit(0); //parent
    }
    fd = open("/dev/null",O_RDWR);
    if(fd<0)
    {
        perror("open()");
        return -1;
    }
    //重定向到0 1 2
    dup2(fd,0);
    dup2(fd,1);
    dup2(fd,2);
    if(fd>2)
    {
        close(fd);
    }
    //脱离控制终端,父进程也结束了,那他的父进程就会变成1号init进程(守护进程的ppid=1)
    setsid();
    chdir("/");
    //不会产生文件了,就不给权限了。
    umask(0);
    return 0;
}

int main()
{
    File *fp;   
    if(daemonize())
    {
        exit(1);
    }
    fp = fopen(FNAME,"w");
    if(fp==NULL)
    {
        perror("fopen()");
        exit(1);
    }
    for(i=0;;i++)
    {
        fprintf(fp,"%d\n",i);
        fflush(fp);
        sleep(1);
    }
    
    exit(0);
}
  1. 系统日志
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容