程序:(静态的概念)源代码,指令

进程:运行着的程序,一个程序可以创建多个进程

线程:线程从属于进程,一个进程可以有多个线程,线程之间共享进程的资源

任务:具体要做的事情(进程 / 线程)

# 获取进程 ID

//linux 编程环境
man getpid // 得到 linux 帮助文档,Linux 的编程手册
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void)
pid_t getppid(void)
//pid_t 类型用于存放进程的 ID 号
getpid() // 返回当前正在运行的进程 ID 号
getppid()  // 返回当前进程额父进程的 ID 号
su    //进入管理权限
cd /     //进入根目录
mkdir C_test  //创建C_test文件夹
cd C_test    //进入此文件夹
nano pid.c   //创建pid.c的文件

图片

//写完代码后输入  ctrl+x   保存并退出
//首次使用Linux环境编译,错误多多,完全没有任何提升和自动语句
gcc pid.c  //编译运行gid.c文件,生成执行文件名a.out
./a.out     //执行pid.c得出执行结果 ctrl+z 停止运行
man pstree  //获得关于pstree 的帮助文档
pstree -p  //得出进程树,谁创建的谁,查看进程树

图片

# 创建进程

man fork   //查看fork的Linux开发手

# fork 函数创建一个孩子进程

需要引用的库

#include <sys/types.h>
#include <unistd.h>
#include <unistd.h>
pid_t fork(void);  // 创建进程通过复制调用进程,新创建的进程称为子进程
// 子进程和父进程运行在不同的区间,相互独立,但父进程和子进程有相同的内容

运行:

nano 2_fork_1.c    //创键c文件

图片

gcc 2_fork_1.c./a.out

图片

输出两个 Hello word!

fork 函数将 A 设为父进程,创建子进程 B,两者内容相同都会输出 hello word

图片

图片

父进程返回子进程的 id 号,子进程的 pid 为零

失败的话,返回 - 1,

图片

图片

cp 2_fork_1.c fork_2.c   // 复制 2_fork_1.c 的代码到 fork_2.c
nano for_2.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(void)
{
        pid_t pid;
        pid = fork();
        printf("pid=%d\n",pid);
        if(pid > 0)
        {
                while(1)
                {
                        printf("hello world\n");
                        sleep(1);
                }
        }
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(void)
{
        pid_t pid;
        pid = fork();
        printf("pid=%d\n",pid);
        if(pid > 0)
        {
                while(1)
                {
                        printf("hello world\n");
                        sleep(1);
                }
        }
       else if(pid == 0)
            {
                    while(1)
                    {
                            printf("Good morning\n");
                            sleep(1);
                    }
            }
        return 0;
}
// 输出结果:交替运行
// 宏观上子进程父进程并发执行,微观上父进程先调度
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(void)
{
        pid_t pid;
        int count =0;
        pid = fork();
        printf("pid=%d\n",pid);
        if(pid > 0)
        {
                while(1)
                {
                        printf("hello world count = %d\n",count++);
                        sleep(1);
                }
        }
        else if(pid == 0)
        {
                while(1)
                {
                        printf("Good morning count = %d\n",count++);
                        sleep(1);
                }
        }
        return 0;
}

父进程和子进程内存是相互独立的。

父进程和子进程的运行没有相互依赖的关系

# 监控子进程 wait 函数

man wait  //等待任意子进程终止,会有返回值,返回那个进程终止,返回其ID号
//引用库
#include <sys/types.h>
#include <unistd.h>
pid_t wait(int *wstatus)  //地址变量,不希望用就设置为空指针

创建三个子进程,五秒钟,10 秒钟,15 秒结束,父进程等所有子进程结束再结束

nano  5_fork.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
//run model:./a.out 10 5 15 (there child process ,after 15s they are over
int main(int argc,char *argv[])
{
        pid_t child_pid;
        int numDead;
        int i;
        for(i =1 ; i < argc; i++)
        {
                switch(fork())
                {
                        case -1: 
                                perror("fork()");
                                exit(0);
                       case 0:
                                printf("child %d started $ = %d, sleeping %s seconds\n", i , getpid(),argv[i]);
                                sleep(atoi(argv[i]));
                                exit(0);
                        default:
                                break;
                }
        }
        numDead = 0;
        while(1)//当前有几个子进程结束了
        {
                child_pid = wait(NULL);  //返回子进程结束的ID号
                if(child_pid==-1)
                {
                        printf("No morre children,Byebye Byebye\n");
                        exit(0);
                }
                numDead++;
                printf("wait() returned child  PID : %d(numDead = %d)\n", child_pid,numDead );
        }
}
//指向
gcc 5_fork.c
./a.out 10 5 15   //运行参数

图片

# 线程函数 pthread_create

//引入库函数
#include <pthread.h>
//创建新的线程
int pthread_create(pthread_t *thread, const pthread_attr_t,void *(*start_routne) (void*),void *arq);)
//第一个参数线程Id号,第二个参数线程结构体指针类型空就是NULL
//第三个函数指针,第四个参数,也可为NULL
//成功返回值为0,错误返回错误数字
//编译的时候末位要加  -pthread

# 等待线程结束

int pthread_join(pthread_t thread,void **retval);
//编译并且链接给 pthread
//调用成功返回零
//第一个为线程参数。等待的线程
//第二个为

编写:

#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
void *thread_function(void *arg);
int main(void)
{
        pthread_t pthread;
        int ret;
        int count=5;//传递子针,传递给线程arg
        //线程用到所有资源都依赖于进程,
        ret = pthread_create(&pthread,NULL,*thread_function,&count);
        if(ret != 0)
        {
                perror("pthread_create");
                exit(1);
        }
        //while(1);//让进程永远不结束,否则线程资源也会被回收
        //使用函数等线程来结束 pthread_join,才会接着运行
        pthread_join(pthread,NULL);
        printf("The thread is over ,process is over too.\n");
        return  0;
}
void *thread_function(void *arg)  //arg为count指针
{       //线程每隔几秒打印
        int i;
        printf("Thread begins running\n");
        for(i = 0; i <= *(int*)arg; i++)
        {
                printf("Hello world\n");
                sleep(1);
        }
}
//编译:
gcc 6_thread.c -pthread  //编译
./a.out  //运行

# 创建两个线程 / 多个线程

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void* thread1_function(void* arg);
void* thread2_function(void* arg);
int count = 5;
int main(void)
{
	pthread_t pthread1,pthread2; //创建新的线程
	int ret;
	//线程用到的所有资源都依赖进程
	ret = pthread_create(&pthread1, NULL, thread1_function,NULL); //创建一个新的线程
	if (ret != 0)
	{
		perror("pthread1_creator");
		exit(1);
	}
	//创建第二个进程
	ret = pthread_create(&pthread2, NULL, thread2_function, NULL);
	if (ret != 0)
	{
		perror("pthread2_creator");
		exit(1);
	}
	//while (1);
	//等线程pthread1结束pthread_join才会接着运行
	pthread_join(pthread1, NULL);
	pthread_join(pthread2, NULL);
	printf("Thre thread is over ,process is over too\n");
	return 0;
} 
void *thread1_function(void* arg) //arg为count指针
{
	//int i;
	printf("Thread1 begin running\n");
	//for (int i = 0; i < *(int*)arg; i++)
	while(1)
	{
		printf("Hello world ");
		sleep(1);
	}
	return NULL;
}
void* thread2_function(void* arg) //arg为count指针
{
	printf("Thread2 begin running\n");
	while (1)
	//for (int i = 0; i < *(int*)arg; i++)
	{
		printf("Good Morning\n");
		sleep(1);
	}
	return NULL;
}

图片

总:父子进程分别打印 count,父进程和子进程会分别独立打印,独立的全局 count 值

进程和线程不同,会使用同一个 count 值是累加的

补:

exit()函数//里面参数为0表示正常退出,为1/-1表示程序异常退出

参考:“嵌入式开发” Linux 简明教程 01~06