一、概述

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

    1.新建类库解决方案,引入命名空间,同时引入要添加UI Form的WebPart(在Portal\UILib目录下) 2.继续UFSoft.UBF.UI.Custom.ExtendedPartBase ...

  2. 《BI那点儿事—数据的艺术》目录索引

    原创·<BI那点儿事—数据的艺术>教程免费发布 各位园友,大家好,我是Bobby,在学习BI和开发的项目的过程中有一些感悟和想法,整理和编写了一些学习资料,本来只是内部学习使用,但为了方便 ...

  3. 展讯camera去除尺寸相关缓存

    amera应用的缓存在/data/data/com.android.camera2/shared_prefs目录下

  4. java利用Scanner获取键盘输入

    首发地址:我的网易博客 在运行一个java程序的时候,可能我们需要在运行的时候传递一些参数进去...咋办呢... java提供了一个Scanner类,利用这个类,我们可以很方便的获取键盘输入的参数.. ...

  5. java:StringBuffer字符处理对象

    1.添加字符 public class StringBufferDemo { public static void main(String args[]) { StringBuffer sbf = n ...

  6. 【转】 如何使用Valgrind memcheck工具进行C/C++的内存泄漏检测

    系统编程中一个重要的方面就是有效地处理与内存相关的问题.你的工作越接近系统,你就需要面对越多的内存问题.有时这些问题非常琐碎,而更多时候它会演变成一个调试内存问题的恶梦.所以,在实践中会用到很多工具来 ...

  7. python3 装饰器

    #Author by Andy#_*_ coding:utf-8 _*_#装饰器的原则及构成:# 原则:# 1.不能修改被装饰函数的源代码.# 2.不能修改被装饰函数的调用方式.# 3.不能改变被装饰 ...

  8. 在cwcity空间上安装phpmyadmin

    上传程序后,安装phpMyAdmin-4.1.4-all-languages.3715384168.zip 出现了错误: Warning: realpath() [function.realpath] ...

  9. [WPF]DataGridHyperlinkColumn网址过长TextTrimming无效

    <DataGridHyperlinkColumn Binding="{Binding source}" Header="来源"> <DataG ...

  10. swift_Class类的继承

    //: Playground - noun: a place where people can play var str = "Hello, playground" //***** ...