一、概述

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

    package com.ljq.utils; import java.io.File; import java.util.ArrayList; import java.util.List; impor ...

  2. RansomNote

    
Given
 an 
arbitrary
 ransom
 note
 string 
and 
another 
string 
containing 
letters from
 all 
th ...

  3. MySQL DML 整理

    DML(Data Manipulation Language)数据操纵语言statements are used for managing data within schema objects. 由D ...

  4. 解决VS2012编写JQuery代码不能智能提示的问题(其他js库的代码提示设置估计类似)

    VS默认设置下编写jQuery代码是这样的: 解决办法: 1.在项目的"管理NuGet程序包"中安装JQuery: 2.打开:工具 -> 选项 -> 文本编辑器 -&g ...

  5. [C语言入门笔记]分支结构与数组

    分支结构与数组 什么是分支结构? 分支结构是用户或者程序可以选择下一步执行哪个语句 分支结构有哪些? If If Else If Else If Switch 在初学者的学习过程中第一种和第二种比较普 ...

  6. 说说ASP.NET的表单验证

    FormsAuthentication是ASP.NET运行时提供的一种Web身份验证方案,以cookie为信息载体,同其它身份验证方案相比,此方案广泛应用于各类的Web应用中,其实现原理其实和具体的W ...

  7. mongodb的一些小总结

    mongodb的安装,官网下载想要的版本,可视化工具mongovue(注意不支持mongodb3.0以上的版本) 下载mis安装,解压后bin,... 1.配置环境变量,将H:\mongodb\mon ...

  8. WebForm复杂控件

    Calendar   日历: FileUpdate 文件上传: Image 图片,可以直接给URL: Repeater: HeaderTemplate - 在加载开始执行一遍 ItemTemplate ...

  9. 关于KINECT2 和ROS接口安装的问题

    具体安装过程见此博客 http://www.itdadao.com/articles/c15a450477p0.html 感谢博主. 注意,在我自己的电脑上,最后测试的两条代码执行不了,即:1)ros ...

  10. org.apache.catalina.webresources.Cache.getResource Unable to add the resource

    org.apache.catalina.webresources.Cache.getResource Unable to add the resource at xxx to the cache be ...