zoukankan      html  css  js  c++  java
  • c 进程和系统调用

    这一篇博客讲解进程和系统调用相关的知识

    有这样一个场景,我需要输入一串文字,然后把我输入的文字加上一个本地的时间戳 保存在一个文件中,可以初步理解为一个备忘录也行

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <time.h>
     4 
     5 /**
     6  *  获取一个当前时间
     7  */
     8 char *now() {
     9     time_t t;
    10     time(&t);
    11     return asctime(localtime(&t));
    12 }
    13 
    14 int main(int argc, const char * argv[]) {
    15     
    16     char comment[80];
    17     char cmd[120];
    18     
    19     fgets(comment, 80, stdin);
    20     // sprintf 把内容写进一个变量中
    21     sprintf(cmd, "echo '%s %s' >> reports.log",comment,now());
    22     // 调用系统的方法来执行这段命令
    23     system(cmd);
    24     return 0;
    25 }

    程序运行的结果是生成了一个文件

    但有时候systemt() 函数也会是不安全的

    sprintf(cmd, "echo ''&& ls / && echo' %s' >> reports.log",now());

    修改上边的代码,然后会得到这样的结果

    列出了根目录下的内容,因此可以使用命令删除文件或启动病毒

     

    那么现在有一个场景,我们有exec来获取本机的网络配置,在Linux 和 Mac 上 你可以用一个叫/sbin/ifconfig的程序 在window上你用ipconfig 

    看代码

     1 #include <stdio.h>
     2 #include <errno.h>
     3 #include <unistd.h>
     4 #include <string.h>
     5 
     6 int main(int argc, const char * argv[]) {
     7     
     8     if (execl("/sbin/ifconfig", "/sbin/ifconfig",NULL) == -1) {
     9         
    10         if (execlp("ipconfig", "ipconfig",NULL) == -1) {
    11             
    12             fprintf(stderr, "Can not run ipconfig : %s",strerror(errno));
    13         }
    14     }
    15     return 0;
    16 }

    下边的代码也是很有意思的,可以充分说明exec函数的作用是停止当前进程 跳到另一个进程的

    我们先创建一个叫做coffee.c 的文件,代码如下

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 int main(int argc, char* argv[]) {
     5     
     6     char *w = getenv("EXTRA");
     7     if (!w) {
     8         w = getenv("FOOD");
     9     }
    10     if (!w) {
    11         w = argv[argc - 1];
    12     }
    13     
    14     char *c = getenv("EXTRA");
    15     if (!c) {
    16         c = argv[argc - 1];
    17     }
    18     
    19     printf("%s with %s 
    ", c, w);
    20     return 0;
    21 }

    该程序的作用是先检测是否有环境变量EXTRA 没有就检测FOOD 如果还没有就给w赋值为最后一个参数值

    先检测环境变量EXTRA 如果没有就给c赋值为最后一个参数

    下边的代码可以检测我们上边这段代码是不是能够正确运行,首先我们新建一个coffeeTest.c的文件

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <errno.h>
     4 #include <unistd.h>
     5 
     6 int main(int argc, char* argv[]) {
     7     
     8     char *my_env[] = {"FOOD=Hanbaobao", NULL};
     9     if (execle("./coffee", "./coffee", "abv", NULL, my_env) == -1) {
    10         fprintf(stderr, "Can not run process: %s",strerror(errno));
    11         return 1;
    12     }
    13     return 0;
    14 }
     gcc coffee.c -o coffee
     gcc coffeeTest.c -o coffeeTest
     ./coffeeTest

    得到的结果是

    abv with Hanbaobao 

    假如我们吧coffeeTest.c中的代码改成这样呢

    1  if (execl("./coffee", "./coffee", "abv", NULL) == -1) {
    2         fprintf(stderr, "Can not run process: %s",strerror(errno));
    3         return 1;
    4     }

    不出意外结果就是 

    abv with abv 

    好了,我们已经了解exec函数的使用方法了,其实exec函数算是程序中的最后一行代码了,只要调用它之后,程序立即停止运行,原理就是停止当前进程开启另外一个进程

    那么如果我们还想要后边的代码继续执行呢

    先看个例子

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <errno.h>
     4 #include <unistd.h>
     5 
     6 int main(int argc, char* argv[]) {
     7     
     8     char *my_env[] = {"FOOD=Hanbaobao", NULL};
     9     
    10     for (int i = 0; i < 3; i++) {
    11         
    12         pid_t pid = fork();
    13         
    14         if (pid == -1) {
    15             fprintf(stderr, "Can not fork process: %s",strerror(errno));
    16             return 1;
    17         }
    18         
    19         if (!pid) {
    20            
    21             if (execle("./coffee", "./coffee", "abv", NULL, my_env) == -1) {
    22                 fprintf(stderr, "Can not run process: %s",strerror(errno));
    23                 return 1;
    24             }
    25         }
    26         
    27         
    28     }
    29     return 0;
    30 }

    如果不加fork() 上边的程序只会打印一次结果,当循环中第一次调用exec的时候,后边的代码就不会再调用了

    fork 是什么,看下边的解释

  • 相关阅读:
    当服务器存在多个与公网访问的网卡(对应不同的公网IP地址)时,如何使用指定的网卡进行HTTP请求
    svn 迁移至 git
    在 sql server 中批量删除表
    从高版本的 SQL Server 向低版本的 SQL Server 转移数据
    MYSQL 复制整个数据库
    在 VS Code 中遇到的一些问题
    把TEMPDB放到内存里
    关于在 ASP.NET 的 Global.asax 中 Application_Error 方法内,设置跳转到自定义错误页无效的问题
    重新安装和更新所有的 nuget包
    高版本 MySQL 导出的脚本到低版本 MySQL 中执行时报错
  • 原文地址:https://www.cnblogs.com/machao/p/5633793.html
Copyright © 2011-2022 走看看