当前位置:首页 » 《随便一记》 » 正文

操作系统实验——进程与线程

1 人参与  2022年11月13日 18:09  分类 : 《随便一记》  评论

点击全文阅读


目录

1.使用GCC

(1)参数

(2)自定义头文件

(3)makefile脚本

(4)gdb调试

2.进程

 (1)新建进程:fork()

(2)执行:exec

(3)消亡:exit()

(4)阻塞:wait()

3.线程

(1)共同操作共享变量

(2)执行顺序控制


1.使用GCC

(1)参数

gcc test.c -o tested 

./tested

(2)自定义头文件

gcc testf.c -o test -I fdhead

-I:指定头文件所在目录,不指定参数将编译出错

#include <stdio.h>#include "math.h"void main(){    int x=2,y=4;    printf("please input two numbers:\n");    //scanf("%d,%d",&x,&y);    printf("x*y=%d\n",Fmulitply(x,y));    printf("x! is %f\n",Ffactorial(x));    printf("y! is %f\n",Ffactorial(y));}
int Fmulitply(int x, int y){    int z;    z=x*y;    return z;}//Fmulitplyfloat Ffactorial(int t){if (t==1)      return 1;else       return (float)t*Ffactorial(t-1);}//Ffactorial

(3)makefile脚本

vi makefile

test:test.c test.h (目标文件:依赖文件)

        gcc test.c –o test (达成目标使用的命令,句子前有一个tab)

make

或 make test (目标名test与makefile中的要一致)

 myfile:

testf2 : testf.c math.hgcc testf.c -o testf2cls : rm testf2

除非特殊指定cls,否则只执行第一个,也就是testf2

(4)gdb调试

2.进程

 (1)新建进程:fork()

fork():一次克隆,两个返回值

父进程返回子进程号,子进程返回0

例:如下图所示,应有几个进程?

4个:父,大儿子,二儿子,孙子

根据pid1和pid2的值可以判断出他们的身份

#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 (pid == 0 && pid2 > 0) {message = "This is the child1\n";x = 10;} else if (pid > 0 && pid2 == 0){message = "This is the child2\n";//父亲第二次克隆孩子x = 20;}else if (pid == 0 && pid2 == 0){message = "This is the child1-child\n";x = 30;}else {message = "This is the parent\n";x = 0;}        printf("%s I'm %d, x=%d,my father is:%d\n",message,x,getpid(),getppid());return 0;}//main

(2)执行:exec

exec是一个函数族,有很多函数,但最后都是下面这个函数执行。

例:

#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/wait.h>int main(void){pid_t a;a = fork();if (a < 0){perror("fork failed");exit(1);}if (a == 0) {printf("child come \n");execlp ("ps" ,"ps",NULL);execlp ("ls" ,"ls","-al","/etc/passwd ",NULL);printf("child exit\n");return 1;} //ifelse {wait(NULL);printf("father exit\n");}//elsereturn 0;}//main

 

execlp ("ps" ,"ps",NULL);    
execlp ("ls" ,"ls","-al","/etc/passwd ",NULL);    

执行第一行时代码就被新的覆盖了,所以不会再执行第二行。

只有exec调用失败返回-1,其后的代码才有可能得到执行。

(3)消亡:exit()

程序执行结束或调用exit后并不是马上消失,而是变为僵死状态

想要观察到孩子的僵死态,需要让父亲睡着,否则先祖会来给孩子收尸

#include <sys/types.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>int main(void){pid_t pid;char *message;int x; pid = fork();if (pid < 0){perror("fork failed");exit(1);}if (pid == 0) {message = "This is the child\n";x = 0; } else {message = "This is the parent\n";x = 10;sleep(10);}      printf("%s I'm %d, x=%d,my father is:%d\n",message,x,getpid(),getppid());return 0;}//main

 &使进程后台执行

22342就是僵尸进程

(4)阻塞:wait()

使调用它的进程等待,进入阻塞状态

子进程死亡会唤醒阻塞的父进程

include <sys/types.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>int main(){pid_t pc1,pc2,pw1,pw2;pc1=fork();pc2=fork();if (pc1>0 && pc2>0) {     //*父进程pw1=wait(NULL);pw2=wait(NULL);printf("***Catch a dead child process with pid: %d\n",pw1);printf("***Catch a dead child process with pid: %d\n",pw2);printf("***I'M %d,THE MAIN PROCESS LEAVE!\n",getpid());}//ifif (pc1==0&&pc2>0) { //*大儿子     printf("===I'M the first child PID:%d,my father is:%d\n",getpid(),getppid());     sleep(10);}//ifif (pc1>0&&pc2==0)  //*二儿子    printf("===I'M the 2nd child PID:%d,my father is:%d,i don't sleep.\n",getpid(),getppid());if (pc1==0&&pc2==0)  //*孙进程    printf("I'M grandson PID:%d,my father is:%d,no one is waiting for me.\n",getpid(),getppid());exit(0);}//main

 

创建出4个进程后,父亲阻塞

大儿子输出以后,沉睡10s

二儿子输出然后死亡,唤醒父亲一次

孙子输出然后死亡,但是唤醒不了大儿子,因为大儿子是sleep而不是wait

直到10s后大儿子死亡,父亲才被真正唤醒,输出三句话。

3.线程

由于pthread库不是Linux系统默认的库,需要使用库libpthread.a,所以,编译连接时,命令后需加“-l pthread” 参数帮助编译器找到相应的库。

创建线程函数   pthread_create

终止线程    pthread_cancel、pthread_exit

线程等待    pthread_join

(1)共同操作共享变量

#include <unistd.h>#include <stdio.h>#include <stdlib.h>//#include <pthread>char message[50] = "Hello World";    //线程共享,初值为helloworldvoid *thread_function(void *arg){int k=0;    printf("===Thread_function1 is running. Argument was %s\n", (char *)arg);//注意此处循环设置过少会使线程执行时间短,测试体现不出并发效果for(k=0;k<10;k++) {sleep(rand()%3);strcpy(message, "THREAD!");}//forpthread_exit("===Thank you for your CPU time!");}void *thread_function2(void *arg){int k=0;    printf("===Thread_function2 is running. Argument was %s\n", (char *)arg);for(k=0;k<10;k++) {sleep(rand()%3);strcpy(message,"ANOTHER THREAD!");}//forpthread_exit("===Thank you for your CPU time!");}int main(){int res,k;pthread_t thread1;pthread_t thread2;void *thread_result;res = pthread_create(&thread1, NULL, thread_function, (void *)message);res = pthread_create(&thread2, NULL, thread_function2, (void *)message);for(k=0;k<20;k++) {      sleep(1);      printf("Message is now %s\n", message);}//forexit(EXIT_FAILURE);}

①线程共享资源: 共同影响进程的message变量

②并发执行: 交替输出message当前的值

(2)执行顺序控制

#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <pthread.h>char message[50] = "Hello World";void *thread_function(void *arg) {    printf("===CHILD run and want to sleep(5). message NOW is %s\n", (char *)arg);    sleep(5);    strcpy(message, "HELLO FATHER!");    pthread_exit("===Thank you for your CPU time!");}int main(){int res;pthread_t threadCH;void *thread_result;res=pthread_create(&threadCH,NULL,thread_function,(void *)message);if(res!=0){perror("thread creation failed");exit(EXIT_FAILURE);}printf("Main thread is waiting for thread to finish by join \n");res=pthread_join(threadCH,&thread_result);if(res!=0){perror("thread join failed\n");exit(EXIT_FAILURE);}printf("child thread returned %s\n",(char *)thread_result);printf("message now is %s\n",message);exit(EXIT_FAILURE);}

 


点击全文阅读


本文链接:http://zhangshiyu.com/post/48234.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1