一.进程

1.进程基本概念

  • 程序:存放在硬盘中的一段数据的集合
  • 进程:程序动态执行的过程,包括创建、调度、消亡的整个过程

2.进程相关命令

1).top

根据CPU占用率查看所有进程任务信息

PID:进程ID号(每个进程唯一),该值>0

PIPID:父进程ID号

2).ps -ef

查看当前系统下所有的进程任务信息

ps -ef | grep 进程名

3).ps -aux

查看进程信息(进程状态)

ps -aux | grep 进程名

4).kill

杀死一个进程任务

kill -9 进程PID

killall -9 进程名

5).&

在后台执行任务

./a.out &

6).ps

查看一个终端所有的前后台任务

7).jobs

查看所有后台任务及其编号

8).fg

将后台任务放到前台执行

9).nicce

使用指定优先级(-20,20)执行进程任务

nice -n 优先级 任务

10).renice

重新设置一个正在运行的进程的优先级

renice -n 优先级 进程PID

3.进程的创建

1).虚拟地址:MMU映射后的可以访问的内存空间

2).物理地址:硬件实际的RAm空间地址,用户一般不允许直接访问物理地址,要通过MMU映射为虚拟地址在进行访问

3).虚拟地址空间分布:

每个进程执行,操作系统会为进程分配0-4G虚拟内存空间

  • 文本段(.text):存放代码和相关指令
  • 数据段:
    • 存放字符串常量(.rodata)
    • 以初始化静态变量、全局变量(.data):在编译时分配空间,程序运行时加载到内存空间中
    • 未初始化静态变量、全局变量(.bss):在进程启动后,由进程默认初始化为0值
  • 栈区(.stack):默认为8M,未经初始化值为随机值,超过变量作用域回收变量空间,增长方向自高向低
  • 堆区(.heap):剩余的空间为堆区,可以有程序员手动申请释放,增长方向自低向高
  • 内核:用户无法访问

4).多个进程的空间(进程空间是独立的):

  • 多进程共用同一虚拟空间地址,但物理空间独立
  • 进程1执行时MMU将进程1的物理地址空间映射到虚拟地址空间中
    进程2执行时MMU将进程2的物理地址空间映射到虚拟地址空间中

4.进程的调度

1).先来先执行,后来后执行

2).短作业优先调度算法

3).高优先级调度算法

4).时间片轮转调度算法

  • CPU在任务中运行的一段时间成为时间片(5-10ms)
  • 宏观并行,微观串行

5).多级队列反馈调度算法

6).负载均衡调度算法

7).抢占式调度算法

5.进程的状态:

1).运行态(R):任务正被CPU执行

2).就绪态(R):任务正处于就绪队列中,但未被CPU调度到

3).可唤醒等待态(S):任务等待某个资源被CPU挂起,等待过程中可以被唤醒

4).不可唤醒等待态(D):任务等待某个资源被CPU挂起,等待过程不能被打断

5).停止态(T):用户将某个任务暂停

6).僵尸态(Z):进程执行结束,空间未被回收

7).结束态(X):进程执行结束,空间也被回收

6.进程相关的函数接口:

1).fork

pid_t  fork(vpid);

功能:创建一个子进程空间

参数:缺省

返回值:

        成功父进程返回子进程的PID

               子进程返回0

        失败返回-1

2).getpid

pid_t  getpid(void);

功能:获得调用进程的PID

3).getppid

pid_t  getppid(void);

功能:获得调用进程的父进程PID

4).exit

void exit(int status);
功能:让进程结束
在主函数中调用exit和return效果相同

5)._exit

void _exit(int status);
功能:直接让进程结束
exit:刷新缓存区,执行一系列进程退出注册的操作,最后让进程结束
_exit:不会刷新缓存区,直接让进程结束

6).wait

pid_t wait(int *wstatus);
功能:回收子进程空间
参数:wstatus:存放子进程结束状态空间的首地址
返回值:
        成功返回回收到的子进程的PID
        失败返回-1
wait:具有阻塞功能,子进程没结束,父进程阻塞等待子进程结束,回收子进程空间
WIFEXITED(wstatus):判断子进程是否正常退出
WEXITSTATUS(wstatus):获得子进程结束时的值
WIFSIGNALED(wstatus):判断子进程是否被信号杀死
WTERMSIG(wstatus):获得杀死子进程信号的值
WCOREDUMP(wstatus):判断子进程是否段错误退出
WIFSTOPPED(wstatus):判断子进程是否被停止
WSTOPSIG(wstatus):获得停止子进程的编号
WIFCONTINUED(wstatus):判断进程是否继续执行

7).waitpid

pid_t waitpid(pid_t pid, int *wstatus, int options);
功能:回收指定的子进程空间
参数:
        pid:回收子进程的ID号、-1表示任意子进程
        wstatus:存放子进程结束状态空间的首地址
        options:
                0 阻塞回收
                WNOHANG 非阻塞回收
返回值:
        成功返回回收到的子进程的PID
        失败返回-1
        如果WNOHANG设置,没有子进程结束,返回0

wait(NULL) == waitpid(-1, NULL, 0);

7.进程的消亡

  • 僵尸态进程如何产生
    • 进程代码执行结束,但是空间没有被回收
  • 如何避免产生僵尸进程
    • 让父进程先结束,子进程成为孤儿进程,孤儿进程会被init进程收养,子进程结束,init回收子进程空间,避免产生僵尸进程
    • 子程序结束,父进程回收子进程空间,避免产生僵尸进程

8.exec函数簇

int execl(const char *path, const char *arg, .../* (char *) NULL */);
int execlp(const char *file, const char *arg, .../* (char *) NULL */);
int execle(const char *path, const char *arg, .../*, (char *) NULL, char
* const envp[ ] */);
int execv(const char *path, char *const argv[ ]);
int execvp(const char *file, char *const argv[ ]);
int execvpe(const char *file, char *const argv[ ], char *const envp[ ]);
功能:利用进程空间执行另外的一段代码
l:参数以列表形式传递
v:参数以指针数组形式传递
p:在环境变量PATH对应的目录下找file
e:更新进程的环境变量

9.ex

下为实例应用

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main(void)
{
    pid_t pid;
    pid = fork();
    if(-1 == pid)
    {
        perror("fail to fork");
        return -1;
    }
    if(0 == pid)
    {
        printf("我是子进程,PID:%d,PPID:%d\n",getpid(),getppid());
    }
    else if(0 < pid)
    {
        printf("我是父进程,PID:%d,PPID:%d\n",getpid(),pid);
    }
    printf("hello world\n");
    return 0;
}

二.线程

1.线程的概念:

  • 线程是轻量级的进程

2.进程和线程的区别:

  • 进程的空间是独立的
  • 线程空间位于进程空间内部,独享栈区(每个线程栈区独立),共享文本区、数据区、堆区(一个进程中的多个线程共用以上区域)
  • 进程是操作系统资源分配的最小单位
  • 线程是CPU任务调度的最小单元

3.线程的创建:

  • 每个线程会创建一个属于该线程的独立的栈空间(默认8M),文本区、数据区、堆区使用进程中的区域

4.线程的调度:

  • 等同于进度调度
  • 宏观并行,微观串行

5.线程的消亡

  • 等同于线程的消亡,线程消亡需要回收线程空间

6.多进程和多线程优缺点:

进程 线程
每个进程空间独立,安全性好,一个进程异常崩溃不会影响其余进程 线程位于进程空间内部,线程异常崩溃会导致进程崩溃,进程中其余的线程均结束
多进程调度,效率低,因为切换进程任务时需要映射不同的物理地址空间,增大系统开销 多线程调度,效率高,因为在同一进程空间内部切换不同的任务
多进程通信不方便,因为空间独立,没有共享空间 多线程通信非常方便,多线程数据区、堆区共享
进程考虑资源竞争问题,因为没有共享空间 通过锁的机制防止资源竞争

7.线程相关函数接口:

1).pthread_create

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void*),void *arg);
功能:创建一个线程任务
参数:
        thread:存放线程ID空间首地址
        attr:线程的属性(大小、优先级等),使用默认属性传NULL
        start_routine:线程函数入口
        arg:线程函数的参数
返回值:
        成功返回0
        失败返回非0

2.pthread_exit

void pthread_exit(void *retval);
功能:结束线程任务
参数:retval:线程结束时的值
返回值:缺省

3.pthread_join

int pthread_join(pthread_t thread, void **retval);
功能:阻塞回收线程空间
参数:
        thread:线程ID
        retval:存放线程结束的状态空间的首地址
返回值:
        成功返回0
        失败返回非0
阻塞回收线程空间
实现线程的同步

4.pthrea_attr_init

int pthread_attr_init(pthread_attr_t *attr);
功能:线程属性初始化为默认值
参数:attr:存放线程属性空间首地址
返回值:
        成功返回0
        失败返回非0

5.pthrea_attr_destroy

int pthread_attr_destroy(pthread_attr_t *attr);
功能:线程属性销毁
参数:attr:存放线程属性空间首地址
返回值:
        成功返回0
        失败返回非0

6.pthrea_attr_setdetachstate

int pthread_attr_setdetachstate(pthread_attr_t *attr, intdetachstate);
功能:设置线程加入/分离属性
参数:
        attr:存放线程属性空间首地址
        detachstate:线程属性
                PTHREAD_CREATE_DETACHED 分离属性
                PTHREAD_CREATE_JOINABLE 加入属性
返回值:
        成功返回0
        失败返回非0

8.线程的属性

  • 加入:线程结束后需要手动回收线程空间(pthread_join)
    • 可以回收线程结束的状态
    • 可以实现线程同步
  • 分离:线程结束后自动回收线程空间
    • 不需要手动回收空间,线程结束由系统自动回收
    • 可以实现多任务先结束先被回收,后结束后被回收
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐