进程与线程
进程的概念还是非常简单,就是程序的一次执行就是一个进程,比如word在磁盘中存储只能是程序,但是当运行起来加载到内存中就成了进程。这时候就程序就成了进程。一个程序的多次执行就会有多个进程。当word退出时进程就结束了。可以简单的理解为进程是程序执行。
线程是进程的运行创建的任务,比如打开word后,系统有了一个word进程,word可以同时打开多个文件,每个文件可以单独编辑打印。每个打开的文件维护系统就是一个线程。
我们每个线程是一个单独系统,当一个进程拥有多个线程时,每个线程可以当做单个运行单元,每个线程有自己的堆、栈、数据区、程序区。因为每个线程油同属于同一个进程。所以可以共享进程的全局数据。所以在数据交流方面非常高效。
一、进程编号
操作系统必须对进程管理,程序运行时进程已经创立,操作系统中有很多进程,操作系统是怎么区分每个进程?每个进程创建时操作系统为了区别每个进程,为每个进程创建了ID。ID是系统自动分配。进程每次建立都会操作系统都要分配ID。而且每个进程不同,同一程序的每次创建进程,操作系统分配的进程不相同。
getpid( )函数用来取得目前进程的进程ID。
使用简单的代码可以获得本进程的ID。
`#include <stdio.h>
#include <unistd.h>
int main( void )
{
printf("进程 ID<%d> \n", getpid());
return 0;
}``
printf(“进程 ID<%d> \n”, getpid());打印出getpid( )函数的返回值。可以发现每次运行时进程的ID都不同。
二、线程
一个线程可以创建若干进程,使用函数
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) ,创建线程。线程可以完成独立的功能。
参数说明:
*pthread_t thread: 指向 pthread_t 类型的指针,用于存储新创建线程的标识符。
const pthread_attr_t attr: 指向 pthread_attr_t 类型的指针,用于指定新线程的属性。如果不需要设置特定属性,可以传递 NULL。
void (start_routine)(void): 新线程的入口函数,即线程执行的函数。这个函数必须有返回值类型 void 并接受一个 void 类型的参数。
void *arg: 传递给线程入口函数的参数,通常是一个指向数据的指针。
返回值:
成功时,函数返回 0。
失败时,返回一个错误编号。
关于函数 pthread_create 参数说明来源Kimi.ai.
pthread_t pthread_self(void) 可以返回线程的ID。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <unistd.h>
static void *new_thread_start(void *arg)
{
printf("新线程: 进程 ID<%d> 线程 ID<%lu>\n", getpid(), pthread_self());
return (void *)0;
}
int main(void)
{
pthread_t tid;
int ret;
ret = pthread_create(&tid, NULL, new_thread_start, NULL);
if (ret) {
fprintf(stderr, "Error: %s\n", strerror(ret));
exit(-1);
}
printf("主线程: 进程 ID<%d> 线程 ID<%lu>\n", getpid(), pthread_self());
sleep(1);
exit(0);
}
main函数启动了一个进程,进程ID是:14079.,主线程ID140406720308992。
pthread_create( )函数创建了一个线程,线程ID 140406711998208。
主线程调用了slepp( )函数,让主进程休眠。确保“新线程”结束后,主线程再结束。
1.#sleep( )函数的作用
sleep( )函数 让当前线程休眠,并且释放CPU资源的拥有权,将CPU的拥有权让渡给其他线程使用。如果不释放CPU的使用权,其他线程无法执行,直到当前运行的线程结束,其他进程才能获得CPU的使用权。无法实现各个线程的并行执行。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <unistd.h>
static void *new_thread_start(void *arg)
{
printf("新线程: 进程 ID<%d> 线程 ID<%lu>\n", getpid(), pthread_self());
for(int m =0; m<10; m++){
printf("新线程: m:%d\n",m);
}
return (void *)0;
}
int main(void)
{
pthread_t tid;
int ret;
ret = pthread_create(&tid, NULL, new_thread_start, NULL);
if (ret) {
fprintf(stderr, "Error: %s\n", strerror(ret));
exit(-1);
}
for(int m =0; m<10; m++){
printf("主线程: m:%d\n",m);
}
printf("主线程: 进程 ID<%d> 线程 ID<%lu>\n", getpid(), pthread_self());
sleep(1);
exit(0);
}
主线程首先占用了CPU,直到主线程执行了sleep( )函数。新线程才获得了CPU的使用权。
2.并行执行
代码如下(示例):
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <unistd.h>
static void *new_thread_start_a(void *arg)
{
printf("新线程_A: 进程 ID<%d> 线程 ID<%lu>\n", getpid(), pthread_self());
for(int m =0; m<10; m++){
printf("新线程_A: m:%d\n",m);
sleep(1);
}
return (void *)0;
}
static void *new_thread_start_b(void *arg)
{
printf("新线程_B: 进程 ID<%d> 线程 ID<%lu>\n", getpid(), pthread_self());
for(int m =0; m<10; m++){
printf("新线程_B: m:%d\n",m);
sleep(1);
}
return (void *)0;
}
int main(void)
{
pthread_t tid;
int ret;
ret = pthread_create(&tid, NULL, new_thread_start_a, NULL);
if (ret) {
fprintf(stderr, "Error: %s\n", strerror(ret));
exit(-1);
}
ret = pthread_create(&tid, NULL, new_thread_start_b, NULL);
if (ret) {
fprintf(stderr, "Error: %s\n", strerror(ret));
exit(-1);
}
for(int m =0; m<10; m++){
printf("主线程: m:%d\n",m);
sleep(1);
}
printf("主线程: 进程 ID<%d> 线程 ID<%lu>\n", getpid(), pthread_self());
sleep(3);
exit(0);
}
使用sleep( )休眠当前线程,CPU的使用权就释放了。其他未休眠的等待线程就获得了CPU的使用权。在遇到sleep( )函数后就释放CPU,其他等待的进程就开始运行了。
总结
在了进程和线程的概念,以及了解线程怎么释放CPU的使用权后,就可以使用多线程的方法来解决问题。。多线程方法可以简化程序的编写。但是需要更多的硬件资源,比如RAM和flash.