Loading... # 环境变量 ## API | 函数 | 说明 | | - | - | | getenv | 获取指定环境变量 | | setenv | 设置环境变量 | | unsetenv | 取消环境变量 | | putenv | 设置环境变量(var=xxx格式)容易出错。 | 环境变量在Lib动态库中导出一个全局变量,使用时直接声明 extern char \*\*environ就可以使用这个变量 ## 代码实践 ``` #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> //声明一下就可以用 extern char **environ; void ShowallEnviron() { for(char** ptr = environ;*ptr!=NULL;++ptr) { puts(*ptr); } } void SetVirton() { setenv("TEST","123455",1); char *test = getenv("TEST"); puts(test); } int main() { SetVirton(); ShowallEnviron(); return 0; } ``` # 进程 对程序来说,进程是由数据,PCB(Process Control Block)组成。 对操作系统来说进程就是PCB 包括正在运行程序全部信息,标识符状态,优先级,内存指针,上下文数据。 PCB是task_struct结构体 大佬帖子详细揭晓 https://blog.csdn.net/gatieme/article/details/51383272 ## Proc源码下载-这部分可不需要 ### 1. 下载Linux命令ps源码 使用which 命令查看命令位置,which ps ![image.png](http://www.irohane.top/usr/uploads/2021/03/1490676644.png) 使用dpkg 命令查看命令所在的源码包,dpkg -S /bin/ps ![image.png](http://www.irohane.top/usr/uploads/2021/03/1859818538.png) 使用 apt-get 命令来下载ls命令所在包的源代码 apt-get source procps 下载到当时目录中 ![image.png](http://www.irohane.top/usr/uploads/2021/03/1271179008.png) ## 使用/Proc 目录获取进程信息 /proc/数字 正在运行的进程ID /proc/PID/status 进程信息、包括进程名、进程ID /proc/PID/cmdline 程序命令行信息 /proc/PID/maps 进程内存映射信息 /proc/PID/mem 进程内存数据(I/O操作) --- 读取内存数据,需要借助ptrace系统调用附加程序才能使用read读取 ## 使用C++获取Proc下的进程ID ``` #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <dirent.h> #include <errno.h> void EnumProc() { // 1. 打开进程目录,其中保存了进程和系统信息 DIR *dir = opendir("/proc"); struct dirent *ent; /* dirent handle */ // 2. 遍历进程目录 while(( ent = readdir(dir) )) { // 3. 解引用获取第一个字符,如果为数字才是ID不为数字就跳出 if(*ent->d_name<'0' || *ent->d_name>'9') continue; // 4. 读取 cmdline 或取二进制文件的路径和参数 char buf[255] = { 0 }; snprintf(buf, 32, "/proc/%s/cmdline", ent->d_name); //打开文件并读取 int fd =open(buf, O_CREAT | O_RDONLY); read(fd, buf, 255); puts(buf); } } int main() { EnumProc(); return 0; } ``` ## 使用C++获取指定进程ID的模块信息 ``` #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <dirent.h> #include <errno.h> // 显示进程模块名称 void proc_show_module(int pid) { char path[266]; sprintf(path, "/proc/%d/maps", pid); FILE *fd = fopen(path, "r"); if (fd == NULL) { printf("无法打开文件 :%s\n", path); return; } // %llx-%llx %4s %x %5s %d %s unsigned long long base = 0, end = 0; char pageatt[5]; int offset; char time[6]; unsigned int inode; while (7 == fscanf(fd, "%llx-%llx %4s %x %5s %d %s", &base, &end, pageatt, &offset, time, &inode, path)) { if (offset == 0) { printf("\t%llx-%llx %4s %x %5s %d %s\n", base, end, pageatt, offset, time, inode, path); } } } int main() { proc_show_module(5786); return 0; } ``` ## 创建进程 Linux创建进程和Windows不一样,Linux通过fork函数创建一个与自身一样的子进程,包括寄存器的状态,内存的变量信息等。 ``` #include <sys/types.h> #include <unistd.h> pid_t fork(void) 返回值三种状态 返回值 -1:创建进程失败 返回值 0:当前程序处于子进程 返回值 >0:当前处于主程序,返回值是子进程PID pid_t wait(int *status); //调用成功返回清理掉进程ID,出错返回-1。父进程如果调用wait 会阻塞,(子进程运行),出错立即返回 pid_t waitpid(pid,pid,int *status,int options) //waitpid 可以等待专属进程。 ``` ### 使用fork创建进程 1. 父进程fork创建一个子进程 2. 系统将父进程空间(PCB)拷贝到子进程中 3. 父进程与子进程都从fork返回(返回值不一样) ![image.png](http://www.irohane.top/usr/uploads/2021/03/61927853.png) ### Exec函数 Exec函数调用后该进程的用户代码和数据代码完全被新程序替换,不会创建进程,从新程序的启动例程开始执行。所以ID并未改变。 | 函数 | 描述 | | - | - | | execl | 把可便参数保存到以NULL结尾的指针数组中 | | execlp | 把可变参数保存到以NULL结尾的指针数组中 | | execle | 把可变参数保存到以NULL结尾的指针数组中 | | execv | 依次在PATH环境变量指示的个目录中查找该程序 | | execvp | 使用enviorn所指向的当前环境变量表 | | execve | | 本质是调用execve 最后修改:2021 年 03 月 02 日 © 允许规范转载 赞 0 如果觉得我的文章对你有用,请随意赞赏