一、概述

  进程和线程网络上有一堆解释,我不喜欢抄袭,也不喜欢套用太教科书的说法。就以我自己的理解来说说进程和线程吧,当然自己的理解肯定不是很严谨,但是理解起来应该会比教科书快一点。进程和线程都可以认为是并发执行程序,但是只有多处理器下的多线程才可以真正实现并发(多个线程在同一个时间片同时运行),其他的实际上并不是真正的并发,都是交替在cpu上运行,只是每个程序运行的时间很短(时间片),快速的交替,所以看上去就是同时在运行(并发)。

  几乎是同样的效果,为什么又分为进程和线程呢?进程和线程最大的区别在于,进程与进程间互不影响,他们拥有各自的完整的虚拟内存,是一个完整的个体。而线程存在于进程中,一个进程可以有很多线程,同一个进程下的线程具有很多共享的内存,比如文件描述符,全局变量等,也有他们私有的数据,如栈区的内存等。所以创建一个线程的开销(占有的资源)远远小于一个进程,这也就是为什么分进程和线程的原因 。

  所以总结一下程序,进程线程的关系吧。一个运行的程序可以有多个进程,一个进程下面可以有多个线程。这就是这三者的关系。要想更加深入地理解这个概念,还是得通过编程去理解。因为理论和实践的关系,马克思已经讨论地不要不要的。

二、概念

  进程号:用于标记一个进程的一个编号。

  僵尸进程:子进程已经结束,但是父进程并没有回收其资源,此时的子进程就是一个僵尸进程。使用wait和waitpid函数可以解决这个问题

  孤儿进程:父进程已经结束,但是子进程仍在运行。这时候子进程就是孤儿进程

  守护进程:一种脱离终端,在后运行的一种进程。终端的开关与他无关。

  PCB:进程控制块。存放进程的管理和控制信息的数据结构。它是进程管理和控制的数据结构,每一个进程均有一个PCB,在创建进程时,建立PCB,伴随进程运行的全过程,直到进程结束和结束。

  进程的状态:三态模型:就绪,运行,阻塞(睡眠)

        五态模型:略

三、套路

  ①进程:fork()创建新进程---->通过fork的返回值分别运行父子进程---->分别写父子进程程序---->父进程等待子进程结束回收资源

  ②线程:套路一:创建一个新的线程---->进入线程函数执行---->主线程等待回收子线程

      套路二:创建一个新的线程---->分离线程---->两个线程毫无瓜葛

四、进程相关函数

1、头文件

  <unistd.h>,<sys/type.h>,<sys/wait.h>

2、shell下查看进程命令

  #ps查看当前进程  #ps -ef  #ps -ax查看所有进程

  参数:STAT:当前进程状态;  TTY:进程从哪个终端启动;  CMD:启动进程所用的命令

3、进程号的类型

  pid_t

4、获取进程号

  pid_t getpid(void)  获取当前进程进程号

  pid_t getppid(void)  获取父进程号

  pid_t getgdid(void)  获取组进程号

5、启动新进程

  ①通过调用system函数来完成,如system(“ps &”),但是这种启动依赖于shell

  ②通过复制当前进程来新建

  pid_t fork(void)  

  子进程从fork函数后开始执行。这是一个特殊的函数,有两个返回值,子进程返回0,父进程返回子进程的PID(进程号)。子进程中大量的数据都是复制的。比如文件描述符,进程上下文等。只有进程号,计时器等少量是子进程所独有的。

6、进程的替换

  因为通过进程的复制得到一个新的进程,但是我们往往生成一个进程需要执行新的任务,所以需要替换掉复制过来的进程,让他去执行我们想要的程序。用exec系列函数来进行替换进程。

  int execl(const char *path, const char *arg, ...,NULL);
  int execlp(const char *file, const char *arg, ...,NULL);
  int execle(const char *path, const char *arg,..., 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[]);

参数:path路径(包括可执行的文件名)  file当前路径可执行的文件名  argv可执行文件选项,例argv={"ps", "ax", 0}注意最后要加0  

   envp环境变量,默认寻找的路径。例:wxvp[]={"PATH = /bin:/user",0}冒号的作用是分隔,表示多个默认路径

7、进程的挂起(休眠,阻塞)

  unsigned int sleep(unsigned int sec)

  两种方式解除挂起:指定的时间到了或者收到信号

8、进程的等待(也是挂起)

  作用是等待子进程结束并回收子进程的资源,避免生成僵尸进程

  ①pid_t wait(int *status)  

  参数:status,存放子进程状态的内存  可以用三个宏来读取status的状态WIFEXITED(status)子进程正常结束则为非0  WEXITSTATUS(status)正常结束则返回退出码  WIFSTOPPED(status)意外终止则为非0

  如果仅仅是回收资源,则wait(NULL);

  ②pid_t waitpid(pid_t pid, int *status, int options)

  等待相应PID子进程结束回收空间

  参数:status 等同于上个函数的status

     pid:>0时  =-1时  =0时  <-1时

     options:不想使用时置0

五、线程相关函数

  1、头文件

    <pthread.h>编译时要加-lpthread选项来连接库

  2、线程号类型

  pthread_t

  3、创建线程函数

  int pthread_create(pthread_t *thread,  const pthread_attr_t *attr, void *(*start_routine) (void *),  void *arg);

  参数:thread存数新线程号的内存  attr线程属性结构体地址,默认用NULL  start_toutine线程函数入口  arg传给线程函数的数,不传值为NULL

  返回值:成功0  失败非0

  4、阻塞线程函数

  int pthread_join(pthread_t thread, void **retval);

  作用:等待子线程结束后,主线程再退出。因为主线程退出后,子线程会全部结束

  retval线程函数的返回值

  返回值:成功0  失败:非0

  5、分离线程函数

  int pthread_detach(pthread_t thread);

  作用:主线程结束会默认结束所有子线程。用这个函数后,主线程结束后不再结束子线程

  返回值:成功0  失败:非0

  6、线程退出函数

  void pthread_exit(void *retval);

  retval存储线程函数数值的变量地址

  返回值:成功0  失败:errno

  7、取消一个正在执行的线程

  int pthread_cancel(pthread_t thread);

  可以取消一个线程。线程默认是可以被取消的,但是也可以设置成不可以被取消

  8、设置线程是否可以被取消

  ①是否可取消int pthread_setcancelstate(int state, int *oldstate);

  state:设置是否可取消的状态PTHREAD_CANCEL_ENABLE可取消  PTHREAD_CANCEL_DISABLE不可取消

  ②是否立即取消int pthread_setcanceltype(int type, int *oldtype);

  PTHREAD_CANCEL_DEFERRED不立即取消,直到取消点取消(取消点包括printf等)  PTHREAD_CANCEL_ASYNCHRONOUS立即取消

  返回值:成功0  失败:errno

  9、线程清理函数

  void pthread_cleanup_push(void (*routine)(void *),void *arg);

  void pthread_cleanup_pop(int execute);

  10、初始化描述线程属性的变量

  int pthread_attr_init(pthread_attr_t *attr);

  参数:attr用于描述线程的属性

  11、对线程变量的清理回收

  int pthread_attr_destroy(pthread_attr_t *attr);

进程和线程及Linux下的编程的更多相关文章

  1. Linux下Socket编程的端口问题( Bind error: Address already in use )

    Linux下Socket编程的端口问题( Bind error: Address already in use ) 在进行linux网络编程时,每次修改了源代码并再次编译运行时,常遇到下面的地使用错误 ...

  2. linux 下 poll 编程

    poll 与 select 很类似,都是对描述符进行遍历,查看是否有描述符就绪.如果有就返回就绪文件描述符的个数将.poll 函数如下: #include <poll.h> int pol ...

  3. Linux 下IOport编程訪问

    曾经写的一篇笔记.偶尔翻出来了,放在这里做个纪念 Linux 下IOport编程訪问 这里记录的方法是在用户态訪问IOport,不涉及驱动程序的编写. 首先要包括头文件 /usr/include/as ...

  4. linux下socket编程实例

    linux下socket编程实例一.基本socket函数Linux系统是通过提供套接字(socket)来进行网络编程的.网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符.s ...

  5. Linux 下shell 编程学习脚手架

    linux body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-t ...

  6. linux下libnet编程 亲自测试可用

    linux下libnet编程 亲自测试可用 亲自测试  如果build包的时候 只要把类型改了 就能改成相应的协议. 0x0800 ip 0x0806 arp 0x86DD    IPv6 0x86e ...

  7. Linux下socket编程基本知识

    本文档主要讲解了Linux下socket编程的一些基本知识,主要包括套接字和字节序的概念,以及一些常用的结构体和函数. 本文是在网易云课堂学习过程中的记录,这个老师讲得很不错,推荐大家围观. Linu ...

  8. linux下shell编程示例-获取进程id

    今天初步学习了一下linux下的shell编程,简单记录一下测试用例 1.编辑shell脚本文件如下: #!/bin/bashecho "hello bash linux"echo ...

  9. Linux下多线程编程

    一.为什么要引入线程? 使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式.在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维 ...

随机推荐

  1. Node聊天程序实例03:chat.js

    作者:vousiu 出处:http://www.cnblogs.com/vousiu 本实例参考自Mike Cantelon等人的<Node.js in Action>一书. chat.j ...

  2. 单例模式getInstance()

    /** * 对象的实例化方法,也是比较多的,最常用的方法是直接使用new,而这是最普通的,如果要考虑到其它的需要,如单实例模式,层次间调用等等. * 直接使用new就不可以实现好的设计好,这时候需要使 ...

  3. iOS开发 滤镜的使用

    iOS开发之滤镜的使用技巧(CoreImage)   一.滤镜的内容和效果是比较多并且复杂的 ,学习滤镜需要技巧 如下: 两个输出语句解决滤镜的属性选择问题: 1.查询效果分类中包含什么效果按住com ...

  4. Linux快捷键

    欢迎和大家交流技术相关问题: 邮箱: jiangxinnju@163.com 博客园地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://g ...

  5. WinForm 公共控件

    一.窗体属性: 1.AcceptButton - 窗体的“接受”按钮.如果设置该属性,每次用户按“Enter”键都相当于“单击”了该按钮. 需要设置哪个键,就在后面选择. 2.CancelButton ...

  6. pandas筛选0,3,6开头的行

    http://stackoverflow.com/questions/15325182/how-to-filter-rows-in-pandas-by-regex dbstk.loc[dbstk.ST ...

  7. PHP 通过Socket收发16进制数据

    最近在php下做关于Socket通讯的相关内容,发现网络上好多人在了解如何进行16进制收发,研究了下,代码如下,欢迎拍砖. <?php        $sendStr = '30 32 30 3 ...

  8. mysql 5.7配置文件参数详解

    read_buffer_size 默认大小:128KB 最大:2GB 最小:8KB 增量:必须为4KB的整数倍,如果配置的不是整数倍,会向下取整 用途: 1.MyISAM表顺序扫描提供的缓存 2.所有 ...

  9. using border-radius to make a worker

    1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...

  10. 2014 NOIP 赛前自我整理提醒。

    空谈WA,实干AC. 所以作为一个就要上战场的OIer ,实干当然是最重要,但刷题不在多,要点牢记是关键,虽然本渣没记住多少,但还是列几点值得注意的小点. 1.战场上容不得失误. 对于每日都要敲键盘的 ...