linux可以创建多个进程。linux支持多进程,可以同时处理多个任务,实现系统资源的最大利用。linux进程间的通信方式:1、利用无名管道pipe;2、利用有名管道(FIFO);3、利用信号single;4、利用共享内存;5、利用消息队列;6、利用信号量。
本教程操作环境:linux7.3系统、Dell G3电脑。
linux可以创建多个进程。
linux 支持多进程。多进程系统的一个好处,就是可以同时处理多个任务,实现系统资源的最大利用。
linux中把正在运行的程序称作进程。
程序:静态的概念,它是一个编译好的二进制文件
进程:动态的概念,当程序运行的时候,系统会自动运行一个对应进程
进程包含了进程控制块(PCB),代码段,数据段三个部分
进程控制块:在linux中是用一个结构体来表示的,记录进程的状态信息
僵尸进程:父进程优先于子进程退出
如果你创建了子进程,但是在父进程中没有回收该子进程的资源,那么该子进程就会变成僵尸进程,僵尸进程最终会由系统中一个叫做INIT的进程回收。
init进程(1号进程)是系统启动的时候运行的第一个进程,是所有进程的祖进程。
死亡态( DEAD): 这是一个已终止的进程,且PCB将会被释放
内核态:也叫内核空间,是内核进程/线程所在的区域。主要负责运行系统、硬件交互。
用户态:也叫用户空间,是用户进程/线程所在的区域。主要用于执行用户程序。
1、区别
内核态:运行的代码不受任何限制,CPU可以执行任何指令。
用户态:不能调度CPU,不能直接访问硬件。运行的代码需要受到CPU的很多检查,不能直接访问内核数据和程序,也就是不可以像内核态线程一样访问任何有效地址。
操作系统在执行用户程序时,主要工作在用户态,只有在其执行没有权限完成的任务时才会切换到内核态。
2、区分用户态和内核态原因
保护机制,防止用户进程误操作或者是恶意破坏系统
保证资源的集中管理,减少资源的使用冲突。
3、用户态切换到内核态方式
(1)系统调用(主动)
系统调用(system call)是操作系统提供给用户进程请求操作系统做一些特权操作的接口,即为用户进程提供服务的窗口。在Linux下可以通过man syscalls命令查看Linux提供的所有系统调用API接口。
由于用户态无法完成某些任务,用户态会请求切换到内核态,内核态通过为用户专门开放的中断完成切换。
(2)外围设备中断(被动)
外围设备发出中断信号,当中断发生后,当前运行的进程暂停运行,并由操作系统内核对中断进程处理,如果中断之前CPU执行的是用户态程序,就相当于从用户态向内核态的切换。
中断用于保证CPU控制权交给操作系统,从而让操作系统可以执行某些操作。
(3)异常(被动)
在执行用户程序时出现某些不可知的异常,会从用户程序切换到内核中处理该异常的程序,也就是切换到了内核态。
1、fork()、vfork()
(1)新建的进程称作子进程,它复制了父进程的所有资源(只在创建的那个时间复制一次,以后全局变量值是不同),父子进程谁先谁后是不确定。
1 2 3 4 5 6 7 8 9 |
|
(2)**vfork()**子进程共享了父进程的所有资源,它一定是子进程先运行,然后才是父进程运行(即使你加上sleep()人为去干扰也是没有用的)
(3)注意
子进程中使用了exit()跟没有使用结果完全不一样
父子进程中是否使用sleep()来让出cpu时间片也是不一样的
父进程中是否使用wait(),waitpid()结果也是不一样的
(4)进程切换执行
1、exit()、_exit()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
1、wait()
1 2 3 4 5 6 |
|
2、 waitpid()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
1 2 3 4 5 6 |
|
不管是进程间的通信,还是线程间的通信。无非都是为了解决一个问题:就是共享资源的分配(协调不同的进程/线程对于共享的资源的访问)
1、传统的进程间通信方式
2、System V IPC对象
3、BSD
1、特点:最原始的进程间的通信方式
它只能在具有亲缘关系的进程间通信(父子进程,兄弟进程);
它没有名字(是存在的);
可以在linux和windows之间的共享中创建(根本就不会生成管道文件),但是有名管道就不可以了(生成管道文件);
半双工通信。
2、无名管道的使用
(1)创建pipe()
1 2 3 4 5 6 |
|
(2)pipe信息收发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
1、特点:随便两个进程之间都行
2、有名管道的使用
(1)创建mkfifo()
1 2 3 4 5 6 7 |
|
(2)FIFO进程信息收发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
|
程序(进程)在运行过程中,外界不定时会发信号给该程序,这个时候该程序面临着两种选择:
不理它(阻塞/忽略)
阻塞:是指将信号挂起,等到程序运行完了再去响应
忽略:舍弃这个信号
响应它
1、linux当中有哪些信号:kill -l 查看
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
(1)1到31号信号称作非实时信号:不支持队列(如果同时来了多个信号,响应是没有规律)
(2)用户自定义的信号 10) SIGUSR1 12) SIGUSR2
(3) 34到64号信号叫做实时信号:支持队列,是linux系统中后面添加进来的信号
信号类似于中断: 硬件 软件
以上信号有两个很特殊:SIGKILL,SIGSTOP不能够被忽略,也不能被阻塞
2、信号相关的操作函数
(1)发送信号kill()
1 2 3 4 5 6 7 8 9 10 |
|
(2)信号的捕捉 signal()
1 2 3 4 5 6 7 8 |
|
(3)等待信号 pause()
1 2 3 4 |
|
(4)信号的阻塞
每个进程都有属于它自己的一个信号掩码(也就是该进程在运行的过程中会阻塞掉的那些信号就被称作信号掩码)。
关于信号掩码操作的一系列函数:
1 2 3 4 5 6 7 8 |
|
(5)配置信号掩码 sigprocmask()—阻塞或解除阻塞信号
1 2 3 4 5 6 7 8 9 |
|
(6)捕捉指定信号并获取信号携带信息sigaction()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
查看共享内存: ipcs -m
删除共享内存: ipcrm -m 共享内存的id
SYSTEM-V ipc通信方式:共享内存、信号量、消息队列。
1、共享内存特点:跟mmap()思想上有些类似
多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等
2、共享内存对应的一系列操作函数
(1)创建共享内存:shmget()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
(2) 映射共享内存到用户空间 shmat()
1 2 3 4 5 6 7 8 |
|
(3)解除映射:shmdt()
1 2 3 4 |
|
(4)删除共享内存:shmctl()
1 2 3 4 5 6 7 8 |
|
3、共享内存简单示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
|
消息队列就是一个消息的列表。用户可以在消息队列中添加消息、读取消息等。
消息队列由消息队列ID来唯一标识
消息队列可以按照类型来发送/接收消息
消息队列的操作包括创建或打开消息队列、添加消息、读取消息和控制消息队列
1、消息队列的特点
写入消息队列的信息,在编写程序的时候会人为的去设置消息的类型(用整数来表示),目的是为了其它进程在读取信息的时候能够准确地通过消息的类型判断要读取的信息。
2、消息队列操作的系列函数
(1)消息队列的创建 msgget()
1 2 |
|
(2)消息队列的收发信息msgsnd()msgrcv()
1 2 3 4 5 6 7 8 9 10 |
|
(3)消息队列的删除 msgctl()
1 2 |
|
3、消息队列通信简单示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
|
信号量协调不同进程对于共享资源的访问,它是不同进程间或一个给定进程内部不同线程间同步的机制。
1、信号量概述
(1)二值信号量
值为0或1。与互斥锁类似,资源可用时值为1,不可用时值为0
(2)计数信号量
值在0到n之间。用来统计资源,其值代表可用资源数
(3)对信号量的操作
P操作:即申请资源,亦即将信号量值减1,可能引起进程睡眠。
V操作:即释放资源,亦即将信号量值加1,V操作从不会睡眠。
等0操作:不申请也不释放资源,而是令进程阻塞直到信号量的值为0为止
2、信号量相关的接口函数
(1) 创建信号量集合semget()
1 2 3 4 5 6 7 |
|
(2)设置/删除信号量集 semctl()
1 2 3 |
|
(3)信号量的PV操作 semop()
核心:信号量为 <=0 时进行p操作,会阻塞程序,直到另一进程中是该信号进行了v操作后,本程序才会继续运行------》key值相同,信号量共通
p 减一操作
v 加一操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
3、信号量协同共享内存示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
|
推荐学习:Linux视频教程
以上是linux可以创建多个进程吗的详细内容。更多信息请关注PHP中文网其他相关文章!