C语言:进程

一、进程标识符pid

类型pid_t,16位整型数三万多个。2的16次方65535.

进程标识是顺次向下使用。与文件描述符不一样。
       pid_t getpid(void);
       pid_t getppid(void);

进程正常终止

1.从main函数返回

2.调用exit

3.调用_exit或_Exit

4.最后一个线程从启动例程返回

5.最有一个线程调用了pthread_exit

进程异常终止

调用abort

接到一个信号并终止

最后一个进行对其取消请求做出响应

二、进程的产生

fork

系统调用,只存在linux环境,duplicating意味着拷贝,克隆。
fork后父子进程的区别:fork返回值不一样,pid不同,ppid也不同,未决信号和文件锁不继承,资源利用量归零。
init进程:所有进程的祖先进程(1号 )
调度器的调度策略会决定哪个程序先运行。

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


int main()
{
    pid_t pid;
    printf("[%d]:Begin() \n",getpid() );
    pid = fork();
    if(pid <0)
    {
        perror("fork()");
        exit(1);
    }
    else if(pid == 0)
    {
        //子进程
        printf("[%d]:Child is working \n",getpid() );
    }
    else
    {
        //父进程
        printf("[%d]:Parent is working \n",getpid() );
    }
    printf("[%d]:end() \n",getpid() );
    return 0;
}

如果把输出打印在终端上begin会打印一次(行缓存),如果打印在文件中begin会打印两次(全缓冲)fork也会拷贝缓冲区内容

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


int main()
{
    pid_t pid;
    printf("[%d]:Begin() ",getpid() );
    fflush(NULL);//需要刷新缓冲区  !!!非常重要
    
    pid = fork();
    if(pid <0)
    {
        perror("fork()");
        exit(1);
    }
    else if(pid == 0)
    {
        //子进程
        printf("[%d]:Child is working \n",getpid() );
    }
    else
    {
        //父进程
        printf("[%d]:Parent is working \n",getpid() );
    }
    printf("[%d]:end() \n",getpid() );
    return 0;
}

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

#define LEFT  30000000
#define RIGHT 30000200

int main()
{
    pid_t pid;
    int i,j,mark;
    for(i = LEFT;i< RIGHT;i++)
    {
        pid = fork();
        if(pid <0)
            exit(1);
        else if(pid == 0)
        {
            mark = 1;
            for(j=2;j<i/2;j++)
            {
                if(i%j ==0)
                {
                    mark = 0;
                    break;
                }
            }

            if(mark)
                printf("%d is a primer \n",i);

            exit(0);
        }
        else
        {

        }

    }

    return 0;
}

fork采用写时拷贝技术,读的情况是不会改变的。谁改变的话,谁就拷贝一份。

vfork

vfork在fork时,指定同一个数据块,不会拷贝,已废弃。

三、进程的消亡与释放资源

wait,waitpid,wait3,wait4

       #include <sys/types.h>
       #include <sys/wait.h>

       pid_t wait(int *wstatus);

       pid_t waitpid(pid_t pid, int *wstatus, int options);
wait用状态接受,可以用宏进行接受判断。(死等)

waitpid,可以接受指定的pid。(options,可以设置不死等 WNOHANG)

wait,相当于wiatpid(-1,&status,0)

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define LEFT  30000000
#define RIGHT 30000200

int main()
{
    pid_t pid;
    int i,j,mark;
    for(i = LEFT;i< RIGHT;i++)
    {
        pid = fork();
        if(pid <0)
            exit(1);
        else if(pid == 0)
        {
            mark = 1;
            for(j=2;j<i/2;j++)
            {
                if(i%j ==0)
                {
                    mark = 0;
                    break;
                }
            }

            if(mark)
                printf("%d is a primer \n",i);

            exit(0);
        }
        else
        {

        }
        
    }
    int st;
    for(i = LEFT;i<RIGHT;i++)
//        wait(&st);
        wait(NULL);  //收尸

    return 0;
}

优化:上面程序使用了200个进程比较消耗资源,采用限制进程的方式对其进行改进。(1.分块法)(2.交叉分配法)(3.池类算法:上游负责仍数据,下游负责抢        )

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define LEFT  30000000
#define RIGHT 30000200
#define N 3

int main()
{
    pid_t pid;
    int i,j,mark;
    int n;
    for(n = 0;n<N;n++)
    {
        pid = fork();
        if(pid < 0)
        {
            exit(1);
        }
        if(pid ==0)
        {
            //子进程

            for(i = LEFT+n;i< RIGHT;i+=N)
            {
                mark = 1;
                for(j=2;j<i/2;j++)
                {
                    if(i%j ==0)
                    {
                        mark = 0;
                        break;
                    }
                }

                if(mark)
                    printf("[%d:%d]%d is a primer \n",n,getpid(),i);
            }
            exit(0);
        }
    }
    for(n=0;n<N;n++)
    {
        wait(NULL);
    }
    return 0;
}

四、exec函数族

       extern char **environ;
       int execl(const char *pathname, const char *arg, ...
                       /* (char  *) NULL */);(路径)
       int execlp(const char *file, const char *arg, ...
                       /* (char  *) NULL */);(有环境变量)
       int execle(const char *pathname, const char *arg, ...
                       /*, (char *) NULL, char *const envp[] */);
       int execv(const char *pathname, char *const argv[]);
       int execvp(const char *file, char *const argv[]);
       int execvpe(const char *file, char *const argv[],
                       char *const envp[]);

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

int main()
{
    puts("Begin");
    fflush(NULL); //不刷新的话缓冲区会直接被替换

    execl("/bin/date","date","+%s",NULL);//出错会继续放下运行,成功就返回
    perror("execl()");
    exit(1);

    puts("End");
    return 0;
}

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

int main()
{
    puts("Begin");
    int pid;
    fflush(NULL);
    pid = fork();
    if(pid <0)
    {
        perror("fork");
        exit(1);
    }
    else if(pid == 0)
    {
        fflush(NULL);
        execl("/bin/date","date","+%s",NULL);
        perror("execl");
        exit(1);
    }
    else
    {
        
    }

    wait(NULL);
    puts("End");


    return 0;

}
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
    puts("Begin");
    int pid;
    fflush(NULL);
    pid = fork();
    if(pid <0)
    {
        perror("fork");
        exit(1);
    }
    else if(pid == 0)
    {
        fflush(NULL);
        //execl("/usr/bin/sleep","sleep","100",NULL);
        execl("/usr/bin/sleep","lxj","100",NULL);// ps -axf 可以看到名字
        perror("execl");
        exit(1);
    }
    else
    {
        
    }

    wait(NULL);
    puts("End");


    return 0;

}

五、用户权限及组权限

-rwsr-xr-x 1 root root 68208 Feb  6 04:49 /usr/bin/passwd*

u+s:别的用户调用可执行文件时,会切换到当前的用户(user)执行。如:passwd命令(红色),sudo命令

g+s:别的用户调用可执行文件时,会切换到同组(group)用户的身份去执行(绿色)

real effective save(exec函数族会鉴定权限)


       uid_t getuid(void);
       uid_t geteuid(void);
        pid_t getgid(void);
       pid_t getegid(void);

         getuid() returns the real user ID of the calling process.

       geteuid() returns the effective user ID of the calling process.

       getgid() returns the real group ID of the calling process.

       getegid() returns the effective group ID of the calling process.

       int setuid(uid_t uid);
       int setgid(gid_t gid);
        int setreuid(uid_t ruid, uid_t euid);
       int setregid(gid_t rgid, gid_t egid);

         

mysu.c

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

int main(int argc,char*argv[])
{
    puts("Begin");
    if(argc <3)
    {
        printf("Usage...\n");
        return 1;
    }
    pid_t pid;
    pid = fork();
    if(pid<0)
    {
        printf("fork\n");
        exit(1);    
    }
    else if(pid ==0)
    {
        setuid(atoi(argv[1]) );
        printf("getuid = %d \n",getuid() );
        execvp(argv[2],argv+2);
        perror("execvp()");
        exit(1);
    }
    else
    {
    }
    wait(NULL);
    puts("End");


    return 0;

}

chown root mysu(添加root用户权限)
chmod u+s (改变权限为 u+s)
./mysu 0 cat /etc/shadow

六、观摩课:解释器文件

也成为脚本文件。sh后缀的文件 #! 开头。

#!/bin/sh

ls 
whoami
cat /etc/shadow

ps

修改/etc/passwd

 56 john:x:1001:1001::/home/john:/usr/bin/top
  56 john:x:1001:1001::/home/john:/usr/local/bin/mysh

七、system

The  system()  library function uses fork(2) to create a child process that executes the shell command specified in command using
       execl(3) as follows:

           execl("/bin/sh", "sh", "-c", command, (char *) NULL);

       system() returns after the command has been completed.
 

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

int main()
{
    system("date +%s > /tmp/out");
 
    return 0;

}

八、进程会计

       int acct(const char *filename);
进程消亡时,会将进程信息写入文件中。

man 2 acct
man 5 acct

九、进程时间

    #include <sys/times.h>

       clock_t times(struct tms *buf);

   struct tms {
               clock_t tms_utime;  /* user time */
               clock_t tms_stime;  /* system time */
               clock_t tms_cutime; /* user time of children */
               clock_t tms_cstime; /* system time of children */
           };

十、守护进程

守护进程又叫精灵进程。满足脱离控制终端,是一个会话(session,标识sid)的leader和一个进程组的leader

  • Process ID(PID)
    Linux中标识进程的一个数字,它的值是不确定的,是由系统分配的(但是有一个例外,启动阶段,kernel运行的第一个进程是init,它的PID是1,是所有进程的最原始的父进程),每个进程都有唯一PID,当进程退出运行之后,PID就会回收,可能之后创建的进程会分配这个PID
  • Parent Process ID(PPID)
    字面意思,父进程的PID
  • Process Group ID(PGID)
    PGID就是进程所属的Group的Leader的PID,如果PGID=PID,那么该进程是Group Leader
  • Session ID(SID)
    和PGID非常相似,SID就是进程所属的Session Leader的PID,如果SID==PID,那么该进程是session leader

Session和Group都是管理多个进程的方式,同一个Group的进程属于同一个Session,一个Session里可以包含多个Group

ps -axj 查看tty为?代表脱离控制终端,PID,SID,PGID相同。 PPID为1         

    pid_t setsid(void);
       int setpgid(pid_t pid, pid_t pgid);
       pid_t getpgid(pid_t pid);

       pid_t getpgrp(void);                 /* POSIX.1 version */
       pid_t getpgrp(pid_t pid);            /* BSD version */

       int setpgrp(void);                   /* System V version */
       int setpgrp(pid_t pid, pid_t pgid);  /* BSD version */

#include<stdlib.h>
#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#define FILENAME "/tmp/out"

static int daemonize()
{
    int pid;
    int fd;
    pid = fork();
    if(pid < 0)
    {
        return -1;
    }
    if (pid == 0)
    {
        fd= open("/dev/null",O_RDWR);
        if(fd <0)
        {
            return -1;
        }
        printf("child fd= %d \n",fd);
        dup2(fd,0);//关闭0 ,让0 指向fd的文件表项, 即标准输出置为空设备
        printf("child fd= %d \n",fd);
        dup2(fd,1);
        dup2(fd,2);
        if(fd >2)
        {
            close(fd);
        }
        setsid(); //实现守护进程的函数
        chdir("/");  //设置工作路径为根路径
//        umask(0);
        return 0;
    }
    else
    {
        return -1;
    }
}

int main()
{
    FILE*fp;
    int count;

    int ret = daemonize();
    printf("ret = %d \n",ret);
    if(ret != 0)
        exit(1);

    fp = fopen(FILENAME,"w");
    if(fp == NULL)
    {
        perror("fopen()");
        exit(1);
    }
    for(count = 0;;count++)
    {
        fprintf(fp,"%d \n",count);

        fflush(fp);
        sleep(1);
    }
    fclose(fp);
    return 0;
}

单实例守护进程:锁文件 /var/run/name.pid。

启动脚本文件:/etc/rc.local。进行添加 

十一、系统日志

/var/log目录下的文件。syslogd服务进行统一管理。

文件名是:syslog

     #include <syslog.h>

       void openlog(const char *ident, int option, int facility);
       void syslog(int priority, const char *format, ...);
       void closelog(void);

#include<stdlib.h>
#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>
#include <errno.h>
#include <string.h>

#define FILENAME "/tmp/out"

static int daemonize()
{
    int pid;
    int fd;
    pid = fork();
    if(pid < 0)
    {
        return -1;
    }
    if (pid == 0)
    {
        fd= open("/dev/null",O_RDWR);
        if(fd <0)
        {
            return -1;
        }
        printf("child fd= %d \n",fd);
        dup2(fd,0);//关闭0 ,让0 指向fd的文件表项, 即标准输出置为空设备
        printf("child fd= %d \n",fd);
        dup2(fd,1);
        dup2(fd,2);
        syslog(LOG_INFO,"child fd = %d",fd);
        if(fd >2)
        {
            close(fd);
        }
        setsid(); //实现守护进程的函数
        chdir("/");  //设置工作路径为根路径
//        umask(0);
        return 0;
    }
    else
    {
        exit(1);
    }
}

int main()
{
    FILE*fp;
    int count;
    openlog("mydaemon",LOG_PID,LOG_DAEMON);

    int ret = daemonize();
    printf("ret = %d \n",ret);
    if(ret != 0)
    {
        syslog(LOG_ERR,"daemonize() failed");
        exit(1);
    }
    else
    {
        syslog(LOG_INFO,"daemonize() successed ret = %d",ret);
    }
    fp = fopen(FILENAME,"w");
    if(fp == NULL)
    {
        syslog(LOG_ERR,"fopen():%s",strerror( errno));
        exit(1);
    }
    syslog(LOG_INFO,"%s was opened",FILENAME);
    for(count = 0;;count++)
    {
        fprintf(fp,"%d \n",count);

        fflush(fp);
        syslog(LOG_DEBUG,"%d is printed",count);
        sleep(1);
    }
    fclose(fp);
    closelog();
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/714634.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

rclone 上传资料到 onedrive 遇到限速问题解决

原因分析 可能和脚本参数设置有关系,我的参数是: rclone copy "F:\阿里云盘\6666\局域网" "od:影视" --ignore-existing -u -v -P --transfers20 --ignore-errors --buffer-size128M --check-first --checkers10 --drive-acknowledge-abuse差不多8G大小的…

C#——值类型和引用类型的区别详情

值类型和引用类型的区别 值类型 值类型&#xff1a; 常用的基本数据类型都是值类型&#xff1a;bool 、char、int、 double、 float、long 、 byte 、ulong、uint、枚举类型、 结构体类型等特点: 在赋值的过程当中&#xff0c;把值的本身赋值给另一个变量&#xff0c;再修改…

关于STM32上用HID HOST调鼠标数据的解析

一、前言 关于这章主要是基于我前面的那篇文章 链接: 关于怎么用Cubemx生成的USBHID设备实现读取一体的鼠标键盘设备&#xff08;改进版&#xff09; https://blog.csdn.net/qq_29187987/article/details/139535648?spm1001.2014.3001.5501 引用的文章的简介 引用的这篇文…

FFmpeg编解码的那些事(3)-视频硬解码的基础知识

目录 前言&#xff1a; 1.iso/os x平台 2.windows平台 3.linux平台 4.Tips&#xff1a; 5.结论&#xff1a; 前言&#xff1a; 视频硬解码的过程就是把视频提取成图片变显示出来&#xff0c;就是播放器播放视频的过程&#xff0c;就可以理解为解码的过程。 在不同的系统…

微信同声传译小程序插件使用教程

微信同声传译小程序插件 —— 机器翻译、智能语音 案例可搜索“一起学英语鸭”小程序查看&#xff0c; 实现效果如下图&#xff1a; 插件功能 语音转文字 语音合成 文本翻译 step 1&#xff1a;添加插件 在使用前&#xff0c;需要登录官网 设置 → 第三方服务 → 添加插件…

UniApp+Vue3使用Vant-微信小程序组件

第一步&#xff1a;打开创建好的UniappVue3的项目 第二步&#xff1a;下载Vant-Weapp npm i vant/weapp -S --production 第三步&#xff1a;修改目录名称 wxcomponents 必须是wxcomponents 第四步&#xff1a;将下载好的vant中的dist目录剪切到当前wxcomponents目录下 第五…

(超详细)基于动态顺序表实现简单的通讯录项目

前言&#xff1a; 我们在上一章节用c语言实现了线性表中的的动态顺序表&#xff0c;那么顺序表就只是顺序表吗&#xff1f;当然不是&#xff0c;使用顺序表结构可以实现很多项目&#xff0c;许多项目的数据结构都会用到顺序表&#xff0c;本章节我们就要使用顺序表实现一个简易…

数值分析笔记(二)函数插值

函数插值 已知函数 f ( x ) f(x) f(x)在区间[a,b]上n1个互异节点 { x i } i 0 n \{{x_i}\}_{i0}^{n} {xi​}i0n​处的函数值 { y i } i 0 n \{{y_i}\}_{i0}^{n} {yi​}i0n​&#xff0c;若函数集合 Φ \Phi Φ中函数 ϕ ( x ) \phi(x) ϕ(x)满足条件 ϕ ( x i ) y i ( i …

论文阅读:RAM++ | Open-Set Image Tagging with Multi-Grained Text Supervision

发表时间&#xff1a;2023年11月16 论文地址&#xff1a;https://arxiv.org/pdf/2310.15200 项目地址&#xff1a;https://github.com/xinyu1205/recognize-anything Recognize Anything Plus Model&#xff08;RAM&#xff09;&#xff0c;这是一种有效利用多粒度文本监督的开…

课时154:项目发布_手工发布_手工发布

1.2.3 手工发布 学习目标 这一节&#xff0c;我们从 基础知识、简单实践、小结 三个方面来学习 基础知识 简介 为了合理的演示生产环境的项目代码发布&#xff0c;同时又兼顾实际实验环境的资源&#xff0c;我们这里将 B主机和C主机 用一台VM主机来实现&#xff0c;A主机单…

电路笔记 :LM3481MM/NOPB升压模块,升压电路原理

LM3481MM/NOPB LM3481MM/NOPB 是德州仪器&#xff08;Texas Instruments&#xff09;的一款广泛应用的DC-DC控制器&#xff0c;常用于电源管理应用&#xff0c;特别是在需要升压&#xff08;boost&#xff09;、反激&#xff08;flyback&#xff09;、SEPIC或反向配置的场合。…

【Ardiuno】实验使用OPT语音模块播放语音(图文)

当我们需要在程序中播放语音内容时&#xff0c;就需要使用到语音模块&#xff0c;今天我们就来实验一下使用OPT语音模块来方法语音。 const int voicePin 5; const int voiceBusyPin 18; const int testLEDPin 2;unsigned long pmillis 0;int busyVal 0; …

Go源码--sync库(3):sync.Pool(2)

回收 回收其实就是将 pool.local 置为空 可以让垃圾回收器回收 我们来看下 源码 func init() {// 将 poolCleanup 注册到 gc开始前的准备工作处理器中在 STW时执行runtime_registerPoolCleanup(poolCleanup) }这里注册了清理程序到GC前准备工作 也就是发生GC前需要执行这段代…

【每日随笔】摩托车控车 ① ( 油离配合 | 落脚油离配合 - 不给油 | 落脚油离配合 - 给油 | 正式油离配合 | 骑行姿态注意事项 )

文章目录 一、找 " 离合结合点 "二、落脚油离配合 ( 不给油 )1、该科目练习目的2、起步姿态3、开始练习 三、落脚油离配合 ( 给油 )1、练习目的2、熟悉油门转速3、练习步骤 四、正式油离配合1、练习目的2、练习步骤3、练习效果 五、骑行姿态注意事项1、基本骑行姿态2…

正能量情感语录热门素材文案去哪里找?文案素材网站分享

正能量情感语录热门素材文案去哪里找&#xff1f;文案素材网站分享 想为你的作品注入正能量和情感温度&#xff1f;不知如何获取热门情感语录素材&#xff1f;别担心&#xff0c;今天我将为大家推荐一些海外知名的素材网站&#xff0c;让你轻松找到受欢迎的文案素材&#xff…

对不起了,QQ和微信,我选择用它!

哈喽&#xff0c;各位小伙伴们好&#xff0c;我是给大家带来各类黑科技与前沿资讯的小武。 每当我们需要在电脑和手机之间传输文件、在学习和工作时与朋友/同事传输文件&#xff0c;相信大多都会使用微信或者QQ。 但是在分享一些软件apk等安装包时&#xff0c;微信和QQ会将其…

.gitignore文件忽略的内容不生效问题解决

文章目录 ①&#xff1a;现象②&#xff1a;原因③&#xff1a;解决 ①&#xff1a;现象 在已经提交过的git管理的项目中&#xff0c; 新增加一个.gitignore文件&#xff0c;文件内忽略内容不生效或者修改.gitignore文件之后&#xff0c;文件内新增的忽略内容不生效 ②&#…

ImageNet-1k 测试集 两大坑

1、官方网站提交test set标签时&#xff0c;千万不能提交zip文件&#xff0c;即便明文说可以 https://image-net.org/challenges/LSVRC/eval_server.php 不然就会浪费一次提交机会&#xff0c;直接提交submission.txt就可以&#xff0c;注意每排5个预测结果&#xff0c;用于计…

第 2 章:Spring Framework 中的 IoC 容器

控制反转&#xff08;Inversion of Control&#xff0c;IoC&#xff09;与 面向切面编程&#xff08;Aspect Oriented Programming&#xff0c;AOP&#xff09;是 Spring Framework 中最重要的两个概念&#xff0c;本章会着重介绍前者&#xff0c;内容包括 IoC 容器以及容器中 …

【UML用户指南】-16-对高级结构建模-构件

目录 1、概念 2、构件与接口 3、可替换性 4、组织构件 5、端口 6、内部结构 6.1、部件 6.2、连接件 7、常用建模技术 7.1、对结构类建模 7.2、对API建模 构件是系统中逻辑的并且可替换的部分&#xff0c;它遵循并提供对一组接口的实现。好的构件用定义良好的接口来定…