进程和线程及Linux下的编程

一、概述

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

时间: 2024-10-07 00:25:16

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

linux下多线程编程

最近研究mysql源码,各种锁,各种互斥,好在我去年认真学了<unix环境高级编程>, 虽然已经忘得差不多了,但是学过始终是学过,拿起来也快.写这篇文章的目的就是总结linux 下多线程编程,作为日后的参考资料. 本文将介绍linux系统下多线程编程中,线程同步的各种方法.包括: 互斥量(mutex) 读写锁 条件变量 信号量 文件互斥 在介绍不同的线程同步的方法之前,先简单的介绍一下进程和线程的概念, 它们的优缺点,线程相关的API,读者——写者问题和哲学家就餐问题. 基础知识 1. 进程和

Linux下Socket编程

http://blog.chinaunix.net/uid-20733992-id-3450058.html 原文地址:Linux下Socket编程 作者:yulianliu1218 Linux下Socket编程 什么是Socket Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序.要学Internet上的TCP/IP网络编程,必须理解Socket接口. Socket接口设计者最先是将接口放在Unix操作系统里面

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

Linux下Socket编程的端口问题( Bind error: Address already in use ) 在进行linux网络编程时,每次修改了源代码并再次编译运行时,常遇到下面的地使用错误: Bind error: Address already in use 虽然用Ctrl+C强制结束了进程,但错误依然存在,用netstat -an |grep 5120和ps aux |grep 5120都还能看到刚才用Ctrl+C“强制结束”了的进程,端口还是使用中,只好每次用kill结束进程,

Linux下Shell编程

Linux的shell编程 1.什么是shell? 当一个用户登录Linux系统之后,系统初始化程序init就为每一个用户运行一个称为shell(外壳)的程序. shell就是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用shell来启动.挂起.停止甚至是编写一些程序.一般的Linux系统都将bash作为默认的shell. 2.几种流行的shell 目前流行的shell有ash.bash.ksh.csh.zsh等,可以用下面的命令来查看she

Linux下socket编程,附带tcp例子

1.网络中进程之间如何通信? 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用(Solaris门和Sun RPC) 但这些都不是本文的主题!我们要讨论的是网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的.其实TCP/IP协议族已经帮我们解决了这个问

根据《linux兵书》目录 在kali上操作 第8章 Linux下的编程

第8章  浑水摸鱼:Linux下的编程 175 8.1  Linux下常用的开发工具 176 8.1.1  GCC 176 8.1.2  CVS 176 8.1.3  Perl 176 8.1.4  Linux上的Delphi--Kylix 177 8.2  Linux下的Vi文本编辑器 177 8.2.1  Vi编辑器介绍 178 8.2.2  启动Vi编辑器 179 8.2.3  显示Vi中的行号 180 8.2.4  光标移动操作 181 8.2.5  屏幕命令 182 8.2.6  文本

linux 下 poll 编程

poll 与 select 很类似,都是对描述符进行遍历,查看是否有描述符就绪.如果有就返回就绪文件描述符的个数将.poll 函数如下: #include <poll.h> int poll(struct pollfd *fdarray, unsigned long nfds, int timeout) 第一个参数指向结构数组第一个元素的指针,每个数组都是一个 pollfd 结构iouyonghu制定额是某个给定描述符的条件. struct pollfd { int fd; short eve

Linux下shell编程实例

1. 判断一文件是不是块或字符设备文件,如果是将其拷贝到 /dev 目录下 read -p "input a file:" filename if [ -b $filename -o -c $filename ] then cp $filename /dev/ fi 2.编写一个脚本,进行简单的减法运算,要求提示输入变量 #!/bin/bash read -p "input a number:" num1 read -p "input another nu

linux下Bash编程组合测试及编写脚本(五)

linux下Bash编程组合测试及编写综合脚本(五) 1.Bash编程组合测试条件 -a: 与关系 -o: 或关系 !: 非关系 表示方法1:[ $# -gt 100 -a $# -le 500 ] 表示方法2:[ $# -gt 100 ] && [ $# -le 500 ] 2.编写一个任意添加与删除用户的脚本,要求如下: 2.1:如果脚本选项是--add:,将添加用户; 如果选项是--del,将删除用户,如果是--help显示帮助信息 2.2:脚本选项后面的参数可任意指定多个用户并且用