linux线程、进程(篇幅一)

进程、线程基础

一、进程基础知识:

1、概念:独立可执行的任务、程序运行和资源管理的最小单位、程序运行的一个过程;
2、特点:动态的(包含了用户数据、程序正文段(程序文本)、系统数据段(PC程序计数器、CPU其他相关寄存器、堆栈数据等));
3、分类:交互进程、批处理进程、守护进程;
4、父进程、子进程、孤儿进程(父进程先退出,后其父进程称为init进程(始祖进程))以及非正常态的进程:僵尸进程(子进程先退出,父进程未处理其退出状态);
5、以上所有进程都统一参与系统的调度,且僵尸进程不动作,占用task_struct空间,依据进程的PID(process ID)进行调度,
同时各进程的优先级由系统默认分配,通过renice函数可以重新分配进程的优先级;
6、进程运行模式:用户模式、内核模式(发起源决定名称);
7、进程状态有四种:运行态、停止态(分为中断型、非中断型)、等待态以及死亡态(类僵尸进程);
8、linux下查看系统进程的指令:ps -axj / ps -aux / top(类似于windows任务管理器);
9、进程在内核中,用一个task_struct以及地址空间映射表组成。

二、线程基础知识:

1、线程是轻量级的进程;
2、线程没有自己独立的内存地址,它与创建它的进程共享同一地址资源,因此线程在运行时需要进程存在,否则会出错;
3、线程与进程统一参与系统的调度,线程减轻了系统在块存储、高速缓存方面卡顿的问题,提高了响应速度、任务切换速度;
4、线程与进程优先级均依靠系统随机分配,也可用函数修改优先级;
5、在uCOS(开源)、vxworks(付费:40万一套)、RT-thread(开源)中,线程也称作任务。

进程可以理解为大任务,线程可理解为小任务。

进程相关函数–>基于Linux操作系统–>文件:sys/types.h、unistd.h

1、创建子进程:fork() 将父进程的代码自fork函数之后全部复制,并同一参与CPU调度,也是“copy-on-write”,无入参,返回值通常是0或子进程的PID号,当返回值是0时,表明当前子进程被系统调用,如果返回的是子进程的PID,表明当前调用的是父进程,因此在公共代码段可以通过pid号来区分父子进程运行的代码,通过getpid()函数可以获取当前调度进程PID,通过getppid()函数可以获取子进程所对应的父进程的PID号;
2、exec函数族:该函数族的本质是替换现有进程
execl(const char *path,const char *a1,const char *a2……)以列表形式列出参数,path是可执行二进制文件路径
execv(const char*path,char *const src[])以数组形式列出参数,path是可执行二进制文件的路径
execle(const char *path,const char *a1,const char *a2……,char *const enviment[])列表形式列出参数,加入环境变量传参
execve
execvp
execlp(const char *file,char *const src[])在path(环境变量中二进制执行文件存放路径)中查找指定可执行文件
3、exit(int)与_exit(int)用于结束进程,前者会刷新缓冲区,后者不会刷新缓冲区,表现为在程序结束时,printf函数在exit()后可以显示出退出前一刻的缓冲区内容,而 _exit()不能显示出来。
4、wait(int *status)和waitpid(pid_t pid,int *status,int options)函数,用来阻塞当前进程,等待某个标志,如果在父进程中,wait()函数等待子进程结束并返回,处理子进程的结束状态,可以有效避免僵尸进程的产生。而waitpid()函数则可以指定等待状态的pid,在父进程中等待指定pid退出,同时可以通过设置参数options来设置函数是否阻塞当前进程来等待指定pid的结束。

创建一个守护进程的一般步骤:

1、首先创建一个孤儿进程(依据孤儿进程定义来创建:父进程先于子进程退出,子进程的父进程变为init进程):*.c文件中,在fork()完成后,强制父进程退出;
2、子进程中建立新的会话期ID:pid_t setsid(void)函数–>创建新的会话期ID,将孤儿进程从终端中剥离出来,使其不再依靠终端运行;
3、修改进程中所复制父进程的所有数据段:修改该进程运行的目录,使得运行不依靠用户home约束、修改文件权限掩码:umask(0)函数、解除所有文件关联,利用getdtablesize()函数和文件描述符关闭函数close(fd)来完成文件关联取消。

线程相关函数:文件–>ptherad.h

注:该线程实现方式是利用第三方线程库来实现的,因此在编译文件时,加上 lpthread库
1、pthread_create( pthread _ t * tid,NULL,void (*func)(int singno),void *src);创建一个线程,同时指定线程运行的函数,以及传参;
2、pthread_join(pthread _ t tid,void **return);阻塞进程,等待指定TID线程并取回其返回值(存放在return中);
3、pthread_exit(void *return);退出当前线程,并把返回值(字符串)放在return中。
4、多线程:利用pthread_create()函数创建多个线程,设置好function后,便进入多线程运行,但是要注意,线程的运行必须有进程支持,否则线程找不到内存资源:段错误,核心已转储。

篇幅限制,分为两篇,下文参照“linux线程、进程(篇幅二)

猜你喜欢

转载自blog.csdn.net/amddma/article/details/77890532