当前位置: 首页 > news >正文

网站开发网页页面跳转合肥最新消息今天

网站开发网页页面跳转,合肥最新消息今天,wordpress login 页面,贵州省城乡建设部官方网站目录 1、进程关键概念 1.什么是程序,什么是进程,有什么区别 2.如何查看系统中有那些进程 3.什么是进程标识符 4.什么叫父进程,什么叫子进程 5.C语言的存储空间是如何分配的 2、进程创建 1.fork函数创建进程 2.vfork函数创建进程 3、…

目录

1、进程关键概念

1.什么是程序,什么是进程,有什么区别

2.如何查看系统中有那些进程

3.什么是进程标识符

4.什么叫父进程,什么叫子进程

5.C语言的存储空间是如何分配的

2、进程创建

1.fork函数创建进程

2.vfork函数创建进程

3、进程退出

1.正常退出

2.异常退出

3.退出状态

4、等待子进程

1.wait函数

2.waitpid函数

3.孤儿进程

5、exec族函数

1.exec族函数的作用

2.exec族函数

3.代码说明

4.补充说明

1.perror函数 

2.whereis命令

 3.pwd命令

4.date命令

5.echo $PATH

6.export PATH=$PATH:......

6、system函数

1.system函数的作用

2.示例 :

7、popen函数

1.函数的作用

2.函数的具体运用

 3.示例:

1、进程关键概念

1.什么是程序,什么是进程,有什么区别

程序是静态的概念比如我们平时使用的qq、微信等都是程序,进程是程序的一次运行活动。一般来说我们的程序跑起来了,系统中就会相应的产生一个或多个进程

2.如何查看系统中有那些进程

1.使用ps指令查看

在实际应用中通常配合grep来查看程序中是否存在某一个进程

例:ps -aux|grep a 这里就会列举出含a的进程grep起到了过滤作用

2.使用top指令查看,top指令类似于Windows里的任务管理器

3.什么是进程标识符

每一个进程都有一个非负整数表示的唯一id,叫做pid,类似于我们的身份证

pid=0;称为交换进程(swapper)作用:进程调度

pid= 1;initial进程,作用:系统初始化

编程调用getpid函数获取自身的进程标识符,getppid是获取父进程的进程表示符

4.什么叫父进程,什么叫子进程

进程a创建了进程b,那么a进程就是父进程b进程就是子进程,父子进程是相对的概念

5.C语言的存储空间是如何分配的

  1. 代码区(Text Segment):

    • 存储程序的机器代码,即编译后的可执行文件。
    • 通常是只读的,防止程序意外修改自身的指令。
    • 包含函数的二进制表示。
  2. 数据区(Data Segment):

    • 存储全局变量、静态变量和常量。
    • 包括已初始化数据区(Initialized Data Segment)和未初始化数据区(BSS段)。
    • 已初始化数据区存储已经明确赋值的全局变量、静态变量和常量。
    • 未初始化数据区存储未被明确赋值的全局变量和静态变量,这部分数据在程序运行前会被初始化为零。
  3. 堆区(Heap):

    • 用于动态内存分配,例如通过 malloccallocrealloc 等函数分配的内存。
    • 堆的大小和位置可以在运行时动态改变。
    • 需要程序员手动管理分配和释放内存,否则可能导致内存泄漏或悬挂指针等问题。
  4. 栈区(Stack):

    • 用于存储函数的局部变量、函数参数、返回地址和函数调用的上下文信息。
    • 每个函数调用都会在栈上分配一块内存,该块在函数返回时会被释放。
    • 栈是一个后进先出(LIFO)的数据结构,通过栈指针(Stack Pointer)来管理。

2、进程创建

父进程与子进程是交替运行的,谁先谁后是由进程调度决定的,在 fork 之后,父进程和子进程会共享相同的代码段、数据段和堆,但各自有独立的栈。当父进程或者子进程需要修改某一处时,系统就会为子进程分配相应的空间(写拷贝)

1.fork函数创建进程

pid_t fork(void);

返回值:

1.返回正数,当前运行的是父进程,返回值就是子进程的pid

2.返回负数,表示调用失败

3.返回0,当前运行的是子进程

2.vfork函数创建进程

pid_t vfork(void);

fork与vfork的区别

1.vfork 直接使用父进程存储空间,不拷贝。

2.vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行。

 创建子进程的一般目的:一个父进程希望复制自己,使父子进程同时执行不同的代码段。这在网络服务进程中是常见的——父进程等待客户端的服务请求。当这种请求到达时,父进程调用fork,创建一个子进程来处理此请求,父进程则继续等待下一个服务请求到达。还有就是一个进程需要执行一个不同的程序时。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main() {// 获取当前进程的PID(进程ID)int pid = getpid();printf("pid = %d\n", pid);// 创建子进程int fork_pid = fork();// 根据fork的返回值判断当前是父进程还是子进程if (fork_pid > 0) {// 父进程while (1) {// 打印父进程和子进程的PIDprintf("pid = %d fork_pid = %d \n", pid, fork_pid);sleep(3); // 休眠3秒}} else if (fork_pid == 0) {// 子进程while (1) {// 打印子进程的PID(子进程内通过getpid获取)// 注意:这里的fork_pid是0,因为在子进程中fork返回0printf("pid = %d fork_pid = %d \n", getpid(), fork_pid);sleep(3); // 休眠3秒}}return 0;
}

3、进程退出

1.正常退出

1.main函数调用return

2.进程调用exit(),标准c库

3.进程调用_exit()或者_Exit(),属于系统调用

补充:进程最后一个线程返回,最后一个线程调用pthread_exit

exit()是对系统调用的封装,调用时会对进程运行产生的缓冲区的内容进行处理再退出,而_exit()是直接退出不处理

2.异常退出

1.调用abort函数使进程异常退出

2.当进程收到某些信号时,如ctrl+c

3.最后一个线程对取消(cancellation)请求做出响应

3.退出状态

不管进程如何终止,最后都会执行内核中的同一段代码。这段代码为相应进程关闭所有打开描述符,释放它所使用的存储器等。一般来说我们都希望终止的进程能够通知父进程它是如何终止的。对于三个终止函数(exit、_exit、_Exit),实现这一点的方法是,将其退出状态作为参数传递给函数。在异常终止情况下,内核(不是进程本身)产生一个指示其异常终止原因的终止状态。在任意一种情况下,该终止进程的父进程都能通过wait或waitpid函数取得其终止状态。

4、等待子进程

父进程等待子进程退出,并收集进程的退出状态

若是子进程退出状态不被收集,就会变成僵尸进程

1.wait函数

pid_t wait(int *status);阻塞等待

参数:

非空:子进程退出状态放在它所指的地址中

空:不关心退出状态

#include <stdio.h>
#include <stdlib.h>int main()
{int con = 0;int pid1 = getpid();int fork_pid = fork();int pid2 = getpid();int status;if(pid1 == pid2){wait(&status);printf("%d\n",status);printf("status = %d\n",WEXITSTATUS(status));while(1){printf("pid1 = %d , pid2 = %d , fork_pid = %d \n",pid1,pid2,fork_pid);sleep(1);}}else if(pid1 != pid2){while(1){printf("pid1 = %d , pid2 = %d , fork_pid = %d \n",pid1,pid2,fork_pid);con++;sleep(1);if(con == 5){exit(33);}}}return 0;
}

2.waitpid函数

pid_t waitpid(pid_t pid, int *status, int options);可以设置成不阻塞等待,但是还是会存在僵尸进程

参数一:

pid==-1 等待任一子进程。就这方面而言,waitpid与wait等效

pid>0等待其进程ID与pid相等的子进程

pid==0等待其组ID等于调用进程组id的任一子进程

pid<-1等待其组ID等于pid绝对值的任一子进程

3.孤儿进程

父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”,此时子进程叫做孤儿进程,Linux避免系统存在过多孤儿进程,init进程会收留孤儿进程,变成孤儿进程的父进程。 

5、exec族函数

1.exec族函数的作用

我们在用fork函数创建子进程后,经常会在新进程中调用exec族函数去执行另外一个程序。当调用exec族函数时,该进程会完全替换为一个新的程序。但是由于exec族函数不会创建新的进程,所以进程的pid并没有改变

当调用 exec 函数时,当前进程的代码、数据和堆栈都被新程序的代码、数据和堆栈所替代。因此,exec 函数族在当前进程的上下文中加载新的程序,而不是创建一个全新的进程。这是 exec 函数族与 fork 函数(用于创建新进程)不同的地方。

2.exec族函数

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[]);
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[]);

返回值:

exec族函数的函数执行成功后不会返回,调用失败时,会设置errno(失败码)并返回-1,然后从原程序的调用点接着往下执行

设置的errno(失败码)可以通过perror()函数来打印函数失败的原因

参数说明:
path:可执行文件的路径
arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束
file:如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录中搜寻可执行文件。

exec族函数参数极难记忆和分辨,函数名中的字符会给我们一些帮助:
l : 使用参数列表
p:使用文件名,并从PATH环境进行寻找可执行文件
v:应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数。
e:多了envp[]数组,使用新的环境变量代替调用进程的环境变量

3.代码说明

execl的使用

#include <stdio.h>
#include <unistd.h>
int main()
{while(1){int pid = fork();if(pid == 0){printf("子进程\n");execl("./zombie01","./zombie01",NULL);}else if(pid > 0){sleep(1);printf("父进程\n");}else{printf("fork no !!!\n");perror("fork");}}return 0;
}

 与下面的execlp做对比

#include <stdio.h>
#include <unistd.h>
int main()
{int dis = execl("/bin/ps","ps",NULL);if(dis == -1){printf("no no no !!!\n");perror("why");}
}

execlp的使用

#include <stdio.h>
#include <unistd.h>
int main()
{printf("exec init \n");if(execlp("ps","ps",NULL)==-1){printf("exec  = -1\n");}return 0;
}

execv的使用

#include <stdio.h>
#include <unistd.h>
int main()
{char *argv[] = {"ls","-l"};if(execv("/bin/ls",argv)==-1){printf("execv no\n");perror("execv");}return 0;
}

4.补充说明

1.perror函数 

perror 函数是一个 C 标准库中的函数,用于将与当前 errno 值相关联的错误消息输出到标准错误流(stderr)

函数原型

void perror(const char *s);

s: 一个字符串,用于在输出错误消息之前打印。通常是程序名或者与错误相关的描述性信息。

perror 会根据 errno 的值输出相应的错误消息。通常在执行系统调用或库函数失败时,errno 会被设置为指示错误的特定代码。

2.whereis命令

whereis命令行工具

用于定位程序的可执行文件、源代码和帮助文档

选项:

  • -b: 查找可执行文件。
  • -m: 查找帮助手册。
  • -s: 指定路径前缀

例如whereis ls

将返回与 ls 相关的信息,包括可执行文件、源代码文件和帮助文档的路径。

注意,whereis 通常用于系统管理员或高级用户,它在不同的系统中可能有不同的行为。在某些系统上,它可能无法找到所有文件,因为它依赖于系统数据库。另外,如果你只想查找可执行文件的位置,你可能更喜欢使用 which 命令

 3.pwd命令

显示当前工作目录的路径

4.date命令

获取当前系统时间

5.echo $PATH

输出系统中设置的 PATH 环境变量的值

6.export PATH=$PATH:......

修改环境变量PATH里的值,$PATH只是表示原先的环境变量,路径之间用':'号隔开后面是需要添加的环境变量

6、system函数

1.system函数的作用

system函数,用于在一个新的进程中执行命令。这个函数会调用系统的 shell 来执行指定的命令。system函数会自己创建一个进程来执行可执行文件或命令,当运行完之后再运行父进程

大致的流程如下:

  1. system 函数调用 fork 来创建一个新的子进程。
  2. 在子进程中,调用 exec 函数来执行指定的命令。
  3. 父进程等待子进程的完成,并获取子进程的退出状态。

函数原型

int system(const char *command);
参数command: 要执行的命令字符串

返回值

  • 如果命令成功执行,system返回一个表示退出状态的值。
  • 如果调用系统 shell 失败或命令无法执行,则返回 -1。

2.示例 :

#include <stdio.h>
#include <unistd.h>
int main()
{printf("exec init \n");if(system("ps")==-1){printf("exec  = -1\n");perror("system");}return 0;
}

在上述例子中,system("ps") 将调用系统的 shell 来执行 "ps" 命令。system函数会等待命令执行完成,然后返回命令的退出状态。如果调用失败,返回 -1。

需要注意的是,system函数的使用可能存在安全风险,特别是在处理用户输入时。如果你需要更加精细的控制和错误处理,可能需要使用更底层的函数,比如 forkexec 组合。

这里可以看一下system的源码

system()函数功能强大,我们直接看linux版system函数的源码:
代码:#include
#include
#include
#includeint system(const char * cmdstring)
{pid_t pid;int status;if(cmdstring == NULL){      return (1);}if((pid = fork())<0){status = -1;}else if(pid == 0){execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);-exit(127); //子进程正常执行则不会执行此语句}else{while(waitpid(pid, &status, 0) < 0){if(errno != EINTER){status = -1;break;}}}return status;
}

7、popen函数

1.函数的作用

popen函数用于创建一个管道并打开一个新的进程或命令。它允许在一个进程中执行一个命令,并通过文件流进行输入和输出。popen返回一个文件指针,可以用于读取命令的输出或向命令传递输入

2.函数的具体运用

popen 会创建一个子进程来执行指定的命令。popen的工作机制涉及到使用 fork 创建一个子进程,然后在子进程中使用 exec 系列函数执行指定的命令。具体来说,popen会创建一个管道,并调用 fork 来创建一个子进程。在子进程中,通过调用 exec 函数来执行指定的命令,这就替换了子进程的映像为要执行的命令。父进程则可以通过管道与子进程通信,可以读取或写入子进程的标准输入和标准输出。在子进程执行完毕后,popen 会关闭相关的管道并等待子进程的结束。然后它会返回一个文件指针,通过这个文件指针你可以读取或写入子进程的标准输出或标准输入。

函数原型

FILE *popen(const char *command, const char *mode);

参数:

  • command: 要执行的命令字符串。
  • mode: 打开文件的模式,可以是 "r"(读取)或 "w"(写入)。

返回值:

  • 如果成功,返回一个指向文件的指针。
  • 如果失败,返回 NULL

 3.示例:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>int main() {char dis[10240] = {0}; // 存储命令输出的缓冲区FILE *file = NULL; // 文件指针用于处理命令输出流// 使用popen打开一个管道并执行 "ls -l" 命令file = popen("ls -l", "r");if (file == NULL) {perror("popen");return -1;}// 读取命令输出到缓冲区,并获取读取的字节数,size_t无符号的整形size_t bytesRead = fread(dis, 1, sizeof(dis) - 1, file);if (bytesRead > 0) {dis[bytesRead] = '\0'; // 在读取的字符串后添加字符串结束符,%z通常用于表示 size_t 类型的值printf("Read %zu bytes:\n%s\n", bytesRead, dis);} else {printf("读取失败.\n");}// 关闭文件指针,等待子进程结束pclose(file);return 0;
}
http://www.khdw.cn/news/31025.html

相关文章:

  • 经典网站设计小吴seo博客
  • 国外注册机网站网销怎么销售的
  • 杭州做网站工作室企业网站有哪些功能
  • 怎么做网站的百度收录武汉网站制作推广
  • 做区块链网站的公司关键词优化武汉
  • 对网站建设的认识商品营销推广的方法有哪些
  • 信誉好的广州外贸网站搜索引擎优化怎么做的
  • asp.net网站转php百度账号设置
  • 做本地网站需要的软件百度手机seo
  • 淮安网站建设要多少钱自助建站系统平台
  • 中小企业网站建设案例semir
  • 住房与城乡建设网站北京网站制作建设公司
  • 做网站运营需要做哪些百度安装免费下载
  • 南京做征信服务的公司网站企业网站的作用
  • 中国工信备案查询网站梅花seo 快速排名软件
  • 购物网站要多少钱cnn头条新闻
  • 做网站后台需要学什么挖掘关键词爱站网
  • 做网站的素材和步骤厦门搜索引擎优化
  • 网站建设合同.doc谷歌浏览器下载官方正版
  • 刷网站跳出率网络推广费用计入什么科目
  • 校园网络设计方案ensp福州seo兼职
  • 如何设立邮箱和网站51网站统计
  • 公司网站建设的系统功能需求北京seo优化分析
  • 山西网站建设设计湖南正规seo优化
  • 网站模版属于侵权吗谷歌地图下载
  • 怎么给网站做seo广告信息发布平台
  • 排名优化推广广州seo招聘网
  • 网站营销推广怎么做网络营销推广广州做seo整站优化公司
  • 手机网站推广怎么做短视频seo排名
  • 专业做网站有哪些关键词录入榜