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 30000200int 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 30000200int 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 3int 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/shls 
whoami
cat /etc/shadowps

修改/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.mzph.cn/bicheng/28365.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软考中级|软件设计师-知识点整理

目录 计算机网络概论 计算机系统基础知识 中央处理单元 数据表示 校验码 计算机体系结构 计算机体系结构的发展 存储系统 输入/输出技术 安全性、可靠性与系统性能评测基础知识 加密技术和认证技术 计算机可靠性 程序设计语言基础知识 程序设计语言概述 程序设计…

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

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

Hadoop的读写流程

Hadoop分布式文件系统(HDFS)是Apache Hadoop项目的核心组件,它为大数据存储提供了一个可靠、可扩展的存储解决方案。本文将详细介绍HDFS的读写数据流程,包括数据的存储原理、读写过程以及优化策略。 一、HDFS简介 HDFS是一个高度容错的分布式文件系统,它设计用于运行在通…

AI探索:最佳落地应用场景

如果说今年的风口&#xff0c;那一定是 AI。不过AI像一把双刃剑&#xff0c;既有助益也有风险。我们将从IBM Watson的高飞与坠落&#xff0c;到Google Allo的黯然失色&#xff0c;探索AI应用中的教训。同时&#xff0c;瑞幸咖啡的成功故事展现了凭借策略得当的AI应用&#xff0…

2024年【安全员-C证】考试资料及安全员-C证找解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 安全员-C证考试资料根据新安全员-C证考试大纲要求&#xff0c;安全生产模拟考试一点通将安全员-C证模拟考试试题进行汇编&#xff0c;组成一套安全员-C证全真模拟考试试题&#xff0c;学员可通过安全员-C证找解析全真…

自学前端第一天

HTML标签 ’HTML‘全程是‘hypertext Markup langage(超文本标记语言) HTML通过一系列的’标签&#xff08;也称为元素&#xff09;‘来定义文本、图像、链接。HTML标签是由尖括号包围的关键字。 标签通常成对存在&#xff0c;包括开始标签和结束标签&#xff08;也称为双标签…

探索AI创新的前沿——从零开始学习和运用SpringAI

1.SpringAI介绍 SpringAI是AI工程师的一个应用框架&#xff0c;它提供了一个友好的API和开发AI应用的抽象&#xff0c;旨在简化AI应用的开发工序。 目标是将可移植性和模块化设计等设计原则应用于AI领域的Spring生态系统&#xff0c;并将POJO作为应用程序的构建块推广到AI领域…

浅谈赚钱的四个级别,你在哪一层呢

一谈到赚钱&#xff0c;很多人都会扯到&#xff1a;智商、情商、人脉、资源、背景等等&#xff0c;类似“小钱靠勤&#xff0c;中钱靠智&#xff0c;大钱靠德”这样的经典语录都会脱口而出&#xff0c;其实从本质上来讲&#xff0c;都没有错&#xff0c;但这样的说法太缥缈&…

mysql-connector下载教程(手把手)

下载一个第三方库主要有三种途径&#xff1a; 去官方网站 Oracle 官网去github去Maven中央仓库 前两个方法比较麻烦&#xff0c;你还需要去找。 这里就只介绍maven的方法 Maven类似于手机app的应用商店。 操作步骤&#xff1a; 点击右边进入官网Maven中央仓库 在搜索框中…

k8s+pv+pvc+nas 数据持久化volumes使用

1 k8s pod申请持久化卷配置 apiVersion: v1 kind: Service metadata:name: $IMG_NAMEnamespace: rz-dtlabels:app: $IMG_NAME spec:type: NodePortports:- port: 8091nodePort: 31082 #service对外开放端口selector:app: $IMG_NAME --- apiVersion: apps/v1 kind: Deployment …

FineReport简单介绍(2)

一、报表类型 模板设计是 FineReport 学习过程中的主要难题所在&#xff0c;FineReport 模板设计主要包括普通报表、聚合报表、决策报表三种设计类型。 报表类型简介- FineReport帮助文档 - 全面的报表使用教程和学习资料 二、聚合报表 2-1 介绍 聚合报表指一个报表中包含多个…

C# —— do_while循环

基本语法 while 循环 先判断条件是否满足 再进行循环 do...while 循环 是先执行一遍 循环体里面的逻辑 再判断是否继续执行 do{// do while 循环语句块Console.WriteLine("这是一个do...while循环");} while (bool值)(循环判断条件);*//*do{Console.WriteLine(&qu…

机器学习笔记 - 用于3D点云数据分割的Point Net的训练

一、数据集简述 ​在本教程中,我们将学习如何在斯坦福 3D 室内场景数据集 ( S3DIS )上训练 Point Net 进行语义分割。S3DIS 是一个 3D 数据集,包含来自多栋建筑的室内空间点云,占地面积超过 6000 平方米。Point Net使用整个点云,能够执行分类和分割任务。如果你一直在关注 …

openstack搭建

openstack搭建 1、虚拟机部署规划 主机主机名IP规划实例通讯内部通讯控制节点controller192.168.10.144192.168.1.144实例节点compute192.168.10.145192.168.1.145 2、硬件配置 主机名内存逻辑CPU数量硬盘容量controller4G480Gcompute4G480G20G 3、安装centos7&#xff0c…

Science:如何快速完成一篇研究性论文?

我是娜姐 迪娜学姐 &#xff0c;一个SCI医学期刊编辑&#xff0c;探索用AI工具提效论文写作和发表。 完成一篇研究性论文&#xff0c;是将长时间积累的研究成果凝聚在几页纸中&#xff0c;对资深科学家而言也是一大挑战。作者们需要在充分论述科学问题和详细展示结果之间找到平…

javaweb 期末复习

1. JDBC数据库连接的实现逻辑与步骤以及JDBC连接配置&#xff08;单列模式&#xff09; public class JDBCUtil {// 这些换成自己的数据库 private static final String DB_URL "jdbc:mysql://localhost:3306/你的数据库名称";private static final String USER &q…

MySQL 保姆级教程(五):数据过滤

第 7 章 数据过滤 7.1 组合 WHERE 子句 MySQL 允许给出多个 WHERE 子句&#xff0c;这些子句可用用两种方式使用&#xff1a;AND 或 OR 操作符 7.1.1 AND 操作符 输入: SELECT server_cost.cost_name,server_cost.cost_value,server_cost.default_value FROM server_cost W…

linux中批量给文件改名

rename 需要批量将文件名前的UC-10_取消掉&#xff0c;以数字来命名文件 rename s/UC-10_// *.jpg 修改成功 要是修改为其他名字需要在单引号的第二个/后加字符即可 例如要改为li

基于 SSM 框架的二手书交易系统

基于 SSM 框架的二手书交易系统 一、项目介绍二、项目技术栈三、项目运行四、项目演示总结 大家好&#xff0c;这里是程序猿代码之路。在当今环保意识日益增强和资源节约型社会建设的背景下&#xff0c;二手交易作为一种节省资源和降低成本的消费方式越来越受到人们的欢迎。特别…

基于Java和SSM框架的多人命题系统

你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果你对多人命题系统感兴趣或者有相关开发需求&#xff0c;文末可以找到我的联系方式。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;Java SSM框架 工具&#xff1a;Eclipse、MySQL Workbench、…