目录
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);}