实验二 进程/线程基本编程练习(操作系统)

(红色字体为分析)

【要求所有练习保留题目要求,在题目要求后面作答:

代码要求有注释,代码中适当标注关键代码为红色。

要有运行结果的截图。

每题最后应该有对程序的适当分析和总结!

注意格式排版,内容分析注意条目,展开清楚地阐述。

1、分析理解多个进程的创建

1)若一个程序中有这样的代码,则有几个进程,父子关系如何?

#include <sys/types.h>

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

int main(void){

pid_t pid,pid2;

char *message;

int x;

pid = fork();

pid2 = fork();

if (pid < 0)

{ perror("fork failed");

exit(1); }

    补充完整后面的代码,使多个进程输出各自身份,并符合正确的亲缘关系

if (  )

{ message = "This is the child\n";

x = 0; }

……

    printf("%s I'm %d, x=%d,my father is:%d\n",message,x,getpid(),getppid());

return 0;

}//main

给出代码及执行效果抓图,并要有说明分析!!!!谁先谁后,为什么。

实验二 进程/线程基本编程练习(操作系统)

实验二 进程/线程基本编程练习(操作系统)

2)若有如下的代码

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

    {

        pid = fork();

……

请分析将产生多少个进程?要有说明分析!!!!

#include <sys/types.h>

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

int main(void){

         pid_t pid;

         char *message;

         int x=0;

         int i;

  

         if (pid < 0)

         {        perror("fork failed");

                   exit(1);     }

         if (pid>0){

          sleep(5);

          message="This is the father\n";

          x=10;

         }

        else{

          message="This is the child\n";

          x=1;

         }

        printf("I'm %d, x=%d,my father is:%d\n",getpid(),x,getppid());

        return 0;

 }

实验二 进程/线程基本编程练习(操作系统)

 

由图可见主进程有五个子进程设分别为进程1,2,3,4,5

进程1有四个子进程分别为1.1  1.2  1.3  1.4

进程2有三个子进程分别为2.1  2.2  2.3

进程1.1同样有三个子进程分别为1.1.1  1.1.2  1.1.3

进程3有两个子进程分别为3.1  3.2

一共为32个进程。

实验二 进程/线程基本编程练习(操作系统)

 

2、解释执行效果

若有下面的功能代码,执行会有怎样的输出?不只有抓图,要有说明分析!!!!谁先谁后,哪里停顿过。

int main(void){

pid_t a;

a = fork();

if (a == 0) {

sleep(2);

execlp ("ps" ,"ps",NULL);

    printf("%s I'm %d, x=%d,my father is:%d\n",message,getpid(),getppid());

}

else

    printf("%s I'm %d, x=%d,my father is:%d\n",message,getpid(),getppid());

return 0;

}

实验二 进程/线程基本编程练习(操作系统)

实验二 进程/线程基本编程练习(操作系统)

子进程睡了一会儿,所以父进程先输出,调用execlp函数ps中的内容覆盖子进程,输出ps的内容,子进程中原来的内容不再输出。

3. 体验进程/线程顺序控制。(基于例5-9,5-11的理解,注意不是用sleep控制

1)编写一个产生父子进程的程序,使执行时子进程先printf出内容,然后父进程再printf输出。

实验二 进程/线程基本编程练习(操作系统)

#include <sys/types.h>

#include <sys/wait.h>

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

int main(void){

        pid_t pid;

        pid_t pw;

        char *message;

        int x;

        pid=fork();

        if(pid<0){

           perror("fork failed");

           exit(1);

         }

        if(pid>0){

         pw=wait(NULL);        //父进程等待子进程结束,子进程结束后父进程才继续执行

         message="This is the father\n";

         x=10;

         }

        else{

         message="This is the child\n";

         x=0;

         }

        printf("%s I'm %d, x=%d, my father is:%d\n",message,getpid(),getppid());

        return 0;

}

  1. 编写一个可产生两个线程(一个输出AAAAAA,一个输出BBBBBB)的程序,代码中要求控制线程输出为AAAAAABBBBBB的顺序。然后修改控制代码重新编译执行,得到另一种输出顺序,得到BBBBBBAAAAAA的输出。

#include <sys/types.h>

#include <sys/wait.h>

#include <unistd.h>

#include <stdio.h>

#include <string.h>

#include <pthread.h>

#include <stdlib.h>

char message[50]="Hello World";

void * thread_function(void *arg)

{

   printf("BBBBBB");

   pthread_exit("child over");

}

void * thread_function2(void *arg)

{

   printf("AAAAAA");

   pthread_exit("child over");

}

int main(){

       int res;

       pthread_t thread,thread2;

       void *thread_result;

res=pthread_create(&thread,NULL,thread_function,(void *)message);

       res=pthread_create(&thread2,NULL,thread_function2,(void *)message);

       if(res!=0){

             perror("thread creation failed!\n");

             exit(EXIT_FAILURE);

       }

       res=pthread_join(thread,&thread_result);

       res=pthread_join(thread2,&thread_result);

}

实验二 进程/线程基本编程练习(操作系统)

#include <sys/types.h>

#include <sys/wait.h>

#include <unistd.h>

#include <stdio.h>

#include <string.h>

#include <pthread.h>

#include <stdlib.h>

char message[50]="Hello World";

void * thread_function(void *arg)

{

   printf("BBBBBB");

   pthread_exit("child over");

}

void * thread_function2(void *arg)

{

   printf("AAAAAA");

   pthread_exit("child over");

}

int main(){

       int res;

       pthread_t thread,thread2;

       void *thread_result;

res=pthread_create(&thread,NULL,thread_function,(void *)message);

       res=pthread_create(&thread2,NULL,thread_function2,(void *)message);

       if(res!=0){

             perror("thread creation failed!\n");

             exit(EXIT_FAILURE);

       }

        res=pthread_join(thread2,&thread_result);

        res=pthread_join(thread,&thread_result);

}

实验二 进程/线程基本编程练习(操作系统)

4. 体验线程对共享变量的处理互斥,否则会出现线程不安全问题。

两个线程对共享的进程变量做加1操作,结果加和是错的5-12),多次运行测试效果,体会程序执行原理,给出认识总结。

实验二 进程/线程基本编程练习(操作系统)

错误解决方法因为pthread并非Linux系统的默认库,而是POSIX线程库。连接时需要使用库libpthread.a,所以在使用pthread_create创建线程时,在编译中要加-lpthread参数。在Linux中将其作为一个库来使用,因此加上 -lpthread(或-pthread)以显式链接该库。

分析:thread1和thread2分别对x和y实现加1操作,正常逻辑下x+y的值应与z相等,但在进程进行的过程中可能会出现x或者y已经加1,但z还没有加1就被打断的情况,所以z还没写入就转入另一个进程,因而出现错误。可在两个进程上加入互斥,从而解决x+y不等于z的情况。

上一篇:C语言线程库的使用


下一篇:unix环境编程 第十二章 12.6线程特定数据