目录

gcc test.c -o tested
./tested
gcc testf.c -o test -I fdhead
-I:指定头文件所在目录,不指定参数将编译出错
- #include
- #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;
- }//Fmulitply
-
- float Ffactorial(int t)
- {
- if (t==1)
- return 1;
- else
- return (float)t*Ffactorial(t-1);
- }//Ffactorial

vi makefile
test:test.c test.h (目标文件:依赖文件)
gcc test.c –o test (达成目标使用的命令,句子前有一个tab)
make
或 make test (目标名test与makefile中的要一致)
myfile:
- testf2 : testf.c math.h
- gcc testf.c -o testf2
- cls :
- rm testf2
除非特殊指定cls,否则只执行第一个,也就是testf2


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
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; } //if
- else {
- wait(NULL);
- printf("father exit\n");}//else
- return 0;
- }//main

execlp ("ps" ,"ps",NULL);
execlp ("ls" ,"ls","-al","/etc/passwd ",NULL);执行第一行时代码就被新的覆盖了,所以不会再执行第二行。
只有exec调用失败返回-1,其后的代码才有可能得到执行。
程序执行结束或调用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就是僵尸进程
使调用它的进程等待,进入阻塞状态
子进程死亡会唤醒阻塞的父进程

- 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()); }//if
- if (pc1==0&&pc2>0) { //*大儿子
- printf("===I'M the first child PID:%d,my father is:%d\n",getpid(),getppid());
- sleep(10); } //if
- if (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后大儿子死亡,父亲才被真正唤醒,输出三句话。
由于pthread库不是Linux系统默认的库,需要使用库libpthread.a,所以,编译连接时,命令后需加“-l pthread” 参数帮助编译器找到相应的库。
需要注意:线程可以创建新线程,两个线程是等同层次,不存在亲缘关系。
#include
创建线程函数:pthread_create
int pthread_create(pthread_t* tid,const pthread_attr_t* attr,void* (*start_rtn),void *restrict arg);
成功返回0,失败返回错误号
(1)tid:事先创建好的pthread_t类型的线程标识符,整型。成功时tid指向的内存单元被设置为新创建线程的线程ID。
(2)attr:设置线程属性,通常设为NULL。
(3)start_rtn:新创建的线程从此函数开始运行,无参数时设为NULL。
(4)arg:start_rtn函数的参数,无参数时设为NULL,有参数时输入参数的地址。当多于一个参数时使用结构体传入。
终止线程: pthread_cancel、pthread_exit
void pthread_exit(void *retval):retval表示线程退出状态,通常传NULL,终止自己。
int pthread_cancel(pthread_t tid):终止同进程中的另一个线程,tid是线程标识符。成功返回0,失败返回错误号
线程等待:pthread_join
pthread_join(tid,void * *retval):主线程等待子线程tid的终止,reval根据终止状态返回不同值。
return返回:reval为返回值
pthread_cancel终止:reval为PTHREAD_CANCEL常量
pthread_exit终止:pthread_exit的参数
对终止状态不感兴趣传NULL
例1:
①线程共享资源: 共同影响进程的message变量
②并发执行: 交替输出message当前的值
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- //#include <pthread>
- //例5-10
-
- char message[50] = "Hello World";
- //线程共享,初值为helloworld
-
- void *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!"); }//for
- pthread_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!"); }//for
- pthread_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);
- } //for
-
- exit(EXIT_FAILURE);
- }
![]()

例2:两个线程对共享的进程变量做加1操作,结果加和是错的。
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <pthread.h>
-
-
- long x=0,y=0,z=0;
- void *thread_function1()
- {
- printf("thread_function1 is running \n");
- while(1)
- {
- x++;
- z++;
- }
- pthread_exit("thank you for your cpu time");
- }
-
- void *thread_function2()
- {
- printf("thread_function2 is running \n");
- while(1)
- {
- y++;
- z++;
- }
- pthread_exit("thank you for your cpu time");
- }
-
- int main(){
- int res;
- pthread_t thread1;
- pthread_t thread2;
-
- res=pthread_create(&thread1,NULL,thread_function1,NULL);//创建子线程
- res=pthread_create(&thread2,NULL,thread_function2,NULL);
-
- sleep(1);
-
- printf(" x= %d\n",x);
- printf(" y= %d\n",y);
- printf(" x+y = %d\n",x+y);
- printf(" z= %d\n",z);
-
- exit(EXIT_FAILURE);
-
- }
按理说x+y=z,但是结果不对。
线程对共享变量的处理应互斥,否则会出现线程不安全问题

- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <pthread.h>
- //例5-11
- 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);
-
- }
