加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
    • 7.4  实验内容
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

进程控制开发之:实验内容

2013/09/13
1
阅读需 23 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

 

7.4  实验内容

7.4.1  编写多进程程序

1.实验目的

通过编写多进程程序,使读者熟练掌握fork()、exec()、wait()和waitpid()等函数的使用,进一步理解在Linux中多进程编程的步骤。

2.实验内容

该实验有3个进程,其中一个为父进程,其余两个是该父进程创建的子进程,其中一个子进程运行“ls -l”指令,另一个子进程在暂停5s之后异常退出,父进程先用阻塞方式等待第一个子进程的结束,然后用非阻塞方式等待另一个子进程的退出,待收集到第二个子进程结束的信息,父进程就返回。

3.实验步骤

(1)画出该实验流程图。

该实验流程图如图7.8所示。

图7.8  实验7.4.1流程图

(2)实验源代码

先看一下下面的代码,这个程序能得到我们所希望的结果吗,它的运行会产生几个进程?请读者回忆一下fork()调用的具体过程。

/* multi_proc_wrong.c */

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <unistd.h>

#include <sys/wait.h>

int main(void)

{

    pid_t child1, child2, child;

    /*创建两个子进程*/

    child1 = fork();

    child2 = fork();

    /*子进程1的出错处理*/

    if (child1 == -1)

    {

        printf("Child1 fork error\n");

        exit(1);

    }

    else if (child1 == 0) /*在子进程1中调用execlp()函数*/

    {

        printf("In child1: execute 'ls -l'\n");

        if (execlp("ls", "ls","-l", NULL)<0)

        {

            printf("Child1 execlp error\n");

        }

    }

  

    if (child2 == -1) /*子进程2的出错处理*/

    {

         printf("Child2 fork error\n");

         exit(1);

    }

    else if( child2 == 0 ) /*在子进程2中使其暂停5s*/

    {

         printf("In child2: sleep for 5 seconds and then exit\n");

         sleep(5);

         exit(0);

    }

    else /*在父进程中等待两个子进程的退出*/

    {

         printf("In father process:\n");

         child = waitpid(child1, NULL, 0); /* 阻塞式等待 */

         if (child == child1)

         {

             printf("Get child1 exit code\n");

         }

         else

         {

             printf("Error occured!\n");

         }

      

         do

         {

             child =waitpid(child2, NULL, WNOHANG);/* 非阻塞式等待 */

             if (child == 0)

             {

                 printf("The child2 process has not exited!\n");

                 sleep(1);

             }

        } while (child == 0);

      

         if (child == child2)

         {

             printf("Get child2 exit code\n");

         }

         else

         {

             printf("Error occured!\n");

         }

    }  

    exit(0);

}

 

编译和运行以上代码,并观察其运行结果。它的结果是我们所希望的吗?

看完前面的代码之后,再观察下面的代码,它们之间有什么区别,会解决哪些问题。

/*multi_proc.c */

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <unistd.h>

#include <sys/wait.h>

int main(void)

{

    pid_t child1, child2, child;

    

    /*创建两个子进程*/

    child1 = fork();

        

    /*子进程1的出错处理*/

    if (child1 == -1)

    {

        printf("Child1 fork error\n");

        exit(1);

    }

    else if (child1 == 0) /*在子进程1中调用execlp()函数*/

    {

        printf("In child1: execute 'ls -l'\n");

        if (execlp("ls", "ls", "-l", NULL) < 0)

        {

            printf("Child1 execlp error\n");

        }

    }

    else /*在父进程中再创建进程2,然后等待两个子进程的退出*/

    {

         child2 = fork();

         if (child2 == -1) /*子进程2的出错处理*/

         {

             printf("Child2 fork error\n");

             exit(1);

        }

        else if(child2 == 0) /*在子进程2中使其暂停5s*/

         {

             printf("In child2: sleep for 5 seconds and then exit\n");

             sleep(5);

             exit(0);

         }

  

         printf("In father process:\n");

         child = waitpid(child1, NULL, 0); /* 阻塞式等待 */

         if (child == child1)

         {

             printf("Get child1 exit code\n");

         }

         else

         {

              printf("Error occured!\n");

         }

      

         do

         {

             child = waitpid(child2, NULL, WNOHANG ); /* 非阻塞式等待 */

             if (child == 0)

             {

                  printf("The child2 process has not exited!\n");

                  sleep(1);

             }

         } while (child == 0);

  

         if (child == child2)

         {

             printf("Get child2 exit code\n");

         }

         else

         {

             printf("Error occured!\n");

         }

    }  

    exit(0);

}

(3)首先在宿主机上编译调试该程序:

$ gcc multi_proc.c –o multi_proc(或者使用Makefile)

(4)在确保没有编译错误后,使用交叉编译该程序:

$ arm-linux-gcc multi_proc.c –o multi_proc (或者使用Makefile)

(5)将生成的可执行程序下载到目标板上运行。

4.实验结果

在目标板上运行的结果如下所示(具体内容与各自的系统有关):

$ ./multi_proc

In child1: execute 'ls -l'        /* 子进程1的显示, 以下是“ls –l”的运行结果 */

total 28

-rwxr-xr-x 1 david root  232 2008-07-18 04:18 Makefile

-rwxr-xr-x 1 david root 8768 2008-07-20 19:51 multi_proc

-rw-r--r-- 1 david root 1479 2008-07-20 19:51 multi_proc.c

-rw-r--r-- 1 david root 3428 2008-07-20 19:51 multi_proc.o

-rw-r--r-- 1 david root 1463 2008-07-20 18:55 multi_proc_wrong.c

In child2: sleep for 5 seconds and then exit /* 子进程2的显示 */

In father process:                                 /* 以下是父进程显示 */

Get child1 exit code                               /* 表示子进程1结束(阻塞等待)*/

The child2 process has not exited!              /* 等待子进程2结束(非阻塞等待)*/

The child2 process has not exited!

The child2 process has not exited!

The child2 process has not exited!

The child2 process has not exited!

Get child2 exit code                               /* 表示子进程2终于结束了*/

因为几个子进程的执行有竞争关系,因此,结果中的顺序是随机的。读者可以思考,怎样才可以保证子进程的执行顺序呢?

 

7.4.2  编写守护进程

1.实验目的

通过编写一个完整的守护进程,使读者掌握守护进程编写和调试的方法,并且进一步熟悉如何编写多进程程序。

2.实验内容

在该实验中,读者首先建立起一个守护进程,然后在该守护进程中新建一个子进程,该子进程暂停10s,然后自动退出,并由守护进程收集子进程退出的消息。在这里,子进程和守护进程的退出消息都在系统日志文件(例如“/var/log/messages”,日志文件的全路径名因版本的不同可能会有所不同)中输出。子进程退出后,守护进程循环暂停,其间隔时间为10s。

3.实验步骤

(1)画出该实验流程图。

该程序流程图如图7.9所示。

图7.9  实验7.4.2流程图

 

(2)实验源代码。

具体代码设置如下:

/* daemon_proc.c */

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <unistd.h>

#include <sys/wait.h>

#include <syslog.h>

int main(void)

{

    pid_t child1,child2;

    int i;

    

     /*创建子进程1*/

    child1 = fork();

    if (child1 ==  1)

    {

         perror("child1 fork");

         exit(1);

    }

    else if (child1 > 0)

    {

        exit(0);        /* 父进程退出*/

    }

    /*打开日志服务*/

    openlog("daemon_proc_info", LOG_PID, LOG_DAEMON);

    

    /*以下几步是编写守护进程的常规步骤*/

    setsid();

    chdir("/");

    umask(0);

    for(i = 0; i < getdtablesize(); i++)

    {

       close(i);

    }

    

    /*创建子进程2*/

    child2 = fork();

    if (child2 ==  1)

    {

         perror("child2 fork");

         exit(1);

    }

    else if (child2 == 0)

    { /* 进程child2 */

      /*在日志中写入字符串*/

        syslog(LOG_INFO, " child2 will sleep for 10s ");

        sleep(10);

        syslog(LOG_INFO, " child2 is going to exit! ");

        exit(0);

    }

    else

    { /* 进程child1*/

        waitpid(child2, NULL, 0);

        syslog(LOG_INFO, " child1 noticed that child2 has exited ");

        /*关闭日志服务*/

        closelog();

        while(1)

        {

             sleep(10);

          }

    }

}

(3)由于有些嵌入式开发板没有syslog服务,读者可以在宿主机上编译运行。

$ gcc daemon_proc.c –o daemon_proc (或者使用Makefile)

(4)运行该程序。

(5)等待10s后,以root身份查看系统日志文件(例如“/var/log/messages”)。

(6)使用ps –ef | grep daemon_proc查看该守护进程是否在运行。

4.实验结果

(1)在系统日志文件中有类似如下的信息显示:

Jul 20 21:15:08 localhost daemon_proc_info[4940]:  child2 will sleep for 10s 

Jul 20 21:15:18 localhost daemon_proc_info[4940]:  child2 is going to exit! 

Jul 20 21:15:18 localhost daemon_proc_info[4939]:  child1 noticed that child2 has exited

读者可以从时间戳里清楚地看到child2确实暂停了10s。

(2)使用命令ps –ef | grep daemon_proc可看到如下结果:

david     4939     1  0 21:15 ?        00:00:00 ./daemon_proc

可见,daemon_proc确实一直在运行。

相关推荐

电子产业图谱

华清远见(www.farsight.com.cn)是国内领先嵌入师培训机构,2004年注册于中国北京海淀高科技园区,除北京总部外,上海、深圳、成都、南京、武汉、西安、广州均有直营分公司。华清远见除提供嵌入式相关的长期就业培训、短期高端培训、师资培训及企业员工内训等业务外,其下属研发中心还负责嵌入式、Android及物联网方向的教学实验平台的研发及培训教材的出版,截止目前为止已公开出版70余本嵌入式/移动开发/物联网相关图书。企业理念:专业始于专注 卓识源于远见。企业价值观:做良心教育、做专业教育,更要做受人尊敬的职业教育。