通信原理课设(gec6818) 005:进程

进程的概念很重要,在后续编写大工程时,有很多地方都需要开辟线程,先来了解进程和线程的概念。

1、概念

上一期的触摸屏,我们知道一般触摸屏是一个死循环,它的操作一般是不会受其他的程序的影响,这个时候需求系统能同时执行多个指令,也就是说进入死循环之后,我们还能执行其他的指令。(比如后期在做音乐播放器时,就需要在实现触摸屏功能的同时,也能播放音乐)

在此之前我们还需要了解并行和并发的区别:并发是一个人同时吃三个馒头,而并行是三个人同时吃三个馒头。并行是指多个处理器或者是多核的处理器同时处理多个不同的任务。 并发是逻辑上的同时发生(simultaneous),一个处理器同时处理多个任务。

由于cpu的核心是有限的,没有办法同时执行这么多条指令。但是cpu的速度是非常快的,它执行一条指令的时间非常短,我们在一个非常短的时间之内进行快速切换,外界的人看起来就像是在并行 ,实际上是并发。

并发将我们的进程分为三个状态
    1 就绪态
    2 运行态
    3 阻塞态

 这三个状态在快速的切换,进程一直在轮询,这么一来,外界看起来这个cpu就像是在同时执行很多个指令。

系统一般分为实时系统与分时系统:
分时系统 --- 基于时间片的调度 
实时系统 --- 中断

并发就是基于时间片的调度。

进程:就是运行起来的这个程序,系统是基于这个进程分配资源的, 每一个进程分配到的资源都是独立的,他们之间是互不影响 --- 他们之间的通信必须要借助系统/网络。
线程:基于进程,属于进程里面的一个并发分支。一个进程里面的多个线程都是共享进程的内存空间,因此他们之间的通信就很简单,一个全局变量即可 ,并且cpu是基于线程进行调度的。

有了进程以后,可以让操作系统从宏观层面实现多应用并发。而并发的实现是通过 CPU 时间片不断切换执行的。对于单核 CPU 来说,在任意一个时刻只会有一个进程在被CPU 调度。

2、函数

有了线程之后,我们就能在宏观层面实现多应用并发。以下是一些常用的进程函数

i.创建线程

线程在系统里面开始的时候是不存在的
我们想用这个线程,我们首先要开辟出这个线程 --- 创建线程

pthread_create - create a new thread
SYNOPSIS
#include <pthread.h>
int pthread_create(
    pthread_t *thread, 
    const pthread_attr_t *attr,
    void *(*start_routine) (void *), 
    void *arg);

参数解释:

thread:用来保存线程的id,后面只要这个线程不死,我们就可以通过这个id来找到这个线程。
attr: 线程的属性,一般我们都是给NULL,表示采用默认属性
start_routine:函数指针,指向你要执行的任务  也就是我们所谓的任务函数,函数的原型:                            void * functionname(void * arg) {}
arg: 为了搞定上面的线程函数的传参问题
返回值:成功返回0,失败返回-1,同时errno被设置

示例:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void * func(void * arg)
{
    int * flag = (int *)arg;
    while(1)
    {
        printf("func %d\n",*flag);
        sleep(1);
    }
}

int main()
{
    //开辟一个线程让它去跑
    pthread_t thread;
    int flag = 1024;
    if(pthread_create(&thread,NULL,func,&flag) != 0)
    {
        perror("pthread create error");
        return -1;
    }
    while(1)
    {
        printf("main\n");
        sleep(1);
    }    
    return 0;    
}

不开辟线程的情况下,主函数进入while(1)后,终端只会打印"main",但由于我们开辟了线程,所以终端能打印"main"、"func 1024",如图所示:

注意,我们要用线程,必须要用这个库pthread。也就是终端进行编译时,必须-lpthread

gcc main.c -o main -lpthread

ii 进程死亡

线程也是需求资源的,默认的情况下面,线程死亡的时候这些资源是不会回收的,我们需要回收这个线程,如果不回收就会成为僵尸线程 -- 占用资源又不做事情。

方式一:等待线程死亡

NAME
pthread_join - join with a terminated thread

SYNOPSIS
#include <pthread.h>
int pthread_join(
	pthread_t thread, 
	void **retval);

方式二:分离模式

NAME
pthread_detach - detach a thread
SYNOPSIS
#include <pthread.h>
int pthread_detach(pthread_t thread);

方式三:分离模式进阶(自己分离自己)推荐

分离自己首先要获取自己线程的id,用pthread_self

NAME
pthread_self - obtain ID of the calling thread

所以自己分离自己

pthread_detach(pthread_self());//自己分离自己

一般我们一来就分离自己,也就是在线程函数的最开始就分离自己。

posted @ 2023-12-29 22:06  Flying3080  Views(25)  Comments(0Edit  收藏  举报  来源