




已阅读5页,还剩60页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
重庆邮电大学移通学院毕业设计 论文 1 重庆邮电大学移通学院毕业设计重庆邮电大学移通学院毕业设计 论文论文 任务书任务书 设计设计 论文论文 题目题目 Linux 多进程编程及应用 学生姓名生姓名 系别系别 计算机 专业专业 计算机科学与技术 班级班级 指导教师指导教师 职称职称 讲师 联系电话联系电话 指导教师所在单位指导教师所在单位 重庆邮电大学移通学院计算机系 主主 要要 研研 究究 内内 容容 方方 法法 和和 要要 求求 要求 熟悉 Linux 内核进程相关代码 熟悉 Linux 多进程编程 内容 1 掌握 Linux 内核进程相关代码 2 掌握 Linux 进程的静态结构 3 熟悉 Linux 进程的创建 调度 及撤销 4 熟悉 Linux 进程间通信 进进 度度 计计 划划 第 4 周 第 6 周 了解 Linux 历史 第 7 周 第 9 周 学习 Linux 进程相关内核代码 第 10 周 第 13 周 学习 Linux 多进程编程 第 14 周 第 15 周 系统性总结及论文撰写 修改论文阶段 主主 要要 参参 考考 文文 献献 1 Daniel P Bovet the kernel analysis Linux programming 重庆邮电大学移通学院毕业设计 论文 目录 4 前前 言言 5 第第 1 章章 LINUX 进程相关内核代码简要分析进程相关内核代码简要分析 6 1 1 基本概念 6 1 1 1 进程 6 1 1 2 轻量级进程和线程 6 1 2 进程的静态结构 7 1 2 1进程描述符 1 3 7 1 3 进程的创建 1 8 8 1 4 Linux 进程调度 1 3 8 9 11 10 1 4 1 总述 10 1 4 2 runqueque结构 1 3 10 1 4 3 runqueque结构分析 3 11 1 5 进程的撤销 3 13 第第 2 章章 LINUX 多进程编程多进程编程 14 2 1 进程的创建 1 2 3 7 15 14 2 1 1 fork 1 3 15 14 2 1 2 fork 与vfork 区别 3 16 2 2 exec 函数族 1 2 3 15 17 2 2 1简介 17 2 2 2 exec 函数族解析 3 18 2 3 进程间通信 1 2 3 4 7 21 2 3 1 总述 21 2 3 2 管道 10 21 2 3 3 信号 4 6 16 29 2 3 4消息队列 3 4 39 2 3 5 共享内存 1 2 3 4 46 2 3 6 Socket 15 48 第第 3 章章 LINUX 多进程编程应用多进程编程应用 51 3 1 Linux 网络服务器中的 51 3 1 1 传统的TCP进程并发服务器程序 15 51 3 1 2 TCP预先派生子进程并发服务器程序 51 结束语结束语 54 致致 谢谢 55 参考文献参考文献 56 附件附件 57 1 英文原文 57 GNU Linux profile 57 重庆邮电大学移通学院毕业设计 论文 前言 5 前前 言言 Linux 是类 UNIX 系统大家族中的一员 从 20 实际 90 年代末开始 Linux 这位相对比较新的成员突然变得非常流行 并且跻身于那些知名的商用 UNIX 操作系统之列 Linux 以其无与伦比的优越性 已经在高档计算机占有了一席之地 而现 今众多 Linux 桌面版的推出也使一般用户能够体验到 Linux 所到来的高性能 和高稳定性 Linux 能够吸引众多的用户不仅仅因为其性能和稳定性 另一个关键的因 素是 Linux 内核的所有源代码对用户开放 这样 任何用户都可以从用户接口 层到与硬件密切相关的核心层 对这个最成功的系统而又最现代的操作系统做 深入的研究 本人所介绍的 Linux 多进程编程所用编程语言为 C 语言 程序测试环为 Ubuntu10 04 C 语言编译器为 GCC4 5 命令解释器为 Bash 本论文的体系主要分为以下几章 第一章 Linux 进程相关内核代码简要分析 第二章 Linux 多进程编程 第三章 Linux 多进程编程应用 重庆邮电大学移通学院毕业设计 论文 第 1 章 Linux 进程相关内核代码简要分 析 6 第第 1 章章 Linux 进程相关内核代码简要分析进程相关内核代码简要分析 1 1 基本概念基本概念 1 1 1 进程进程 进程是任何多任务操作系统中的基本概念 通常把进程定义为一个应用程 序运行实例 如果当前有 n 个用户同时运行一个程序 例如 mplayer 那么就有 n 个独立的进程 尽管它们共享同一段可执行代码 1 1 2 轻量级进程和线程轻量级进程和线程 为什么这个部分要将轻量级进程和线程同时提出 因为在 Linux 系统很少 使用线程的概念 为什么 Linux 要很少使用线程的概念 因为线程在处理一些 任务的时候性能并不令人满意 例如 现在我们有一个 GUI Graphical User Interface 简称 GUI 又称图形用户接口 程序 程序分为两部分 其一是图形 处理部分 其二是后台数据处理 可以将这两部分分为两个线程 如果这个程 序是一个单独的进程 就会出现这样的问题 图形处理线程会常常阻塞等待用 户的各种操作 这样就会导致数据处理的线程也会阻塞 相反 图形处理线程 要使用非常复杂的非阻塞技术来确保进程是运行的 为了解决上述问题 Linux 传奇式的引入了一个轻量级进程的概念 此概 念只存在在 Linux 系统中 轻量级进程是线程的替代 轻量级进程其实就是一 个普通的进程 不同的是几个轻量级进程之间可以共享资源 如地址空间 打 开的文件 只要其中一个修改共享资源 另一个就会立即查看这种修改 当两 个轻量级进程访问共享资源是就必须同步它们 虽然 Linux 很少使用线程的概念 但任然提供了线程的支持 具体可参考 pthread h 重庆邮电大学移通学院毕业设计 论文 第 1 章 Linux 进程相关内核代码简要分 析 7 1 2 进程的静态结构进程的静态结构 1 2 1 进程描述符进程描述符 1 3 为了管理进程 内核必须对每个进程做清晰的描述 Linux 内核代码中进 程描述数据结构 task struct 存放在 include linux sched h 1 3 头文件中 Linux 进程描述符中所包含的信息有进程标识符 PID 进程所占内存区域 相关文件的文件描述符 安全信息 进程环境 信号处理 资源安排 同步处 理 和进程状态几个方面 1 3 task struct 结构中的的几个特殊成员 进程状态 定义在 sched h 头文件中 define TASK RUNNING 0 正在运行中的进程 define TASK INTERRUPTIBLE 1 等待队列中的进程 等待资源有效时唤醒进入就绪 队列 define TASK UNINTERRUPTIBLE 2 等待队列中的进程 等待资源有效时唤醒 但不可 被其他进程中断 define TASK STOPPED 4 进程暂停 通过其他信号才能唤醒 define TASK TRACED 8 进程处理跟踪状态 define EXIT ZOMBIE 16 僵尸状态task数组中任然有个tast struct数据结构 项 它只等待父进程将他释放 define EXIT DEAD 32 最终状态 父进程发出wait4 调用或waitpid 调 用 进程由系统删除 2 进程标志位 flags define PF ALIGNWARN0 x00000001 打印对齐警告短信息 define PF STARTING0 x00000002 进程被创造 define PF EXITING0 x00000004 标志进程开始关闭 define PF DEAD0 x00000008 僵尸进程 define PF FORKNOEXEC 0 x00000040 进程刚创建但没有运行 define PF SUPERPRIV0 x00000100 使用超级用户权限 define PF DUMPCORE0 x00000200 标志是否清空core文件 define PF SIGNALED0 x00000400 标志进程被信号signal终止 define PF MEMALLOC0 x00000800 标志进程正在分配内存 define PF FLUSHER0 x00001000 磁盘回写 define PF USED MATH0 x00002000 如果不进行初始化的fpu必须在使用前 define PF FREEZE 0 x00004000 进程被暂停 重庆邮电大学移通学院毕业设计 论文 第 1 章 Linux 进程相关内核代码简要分 析 8 define PF NOFREEZE 0 x00008000 进程未被暂停 define PF FROZEN 0 x00010000 系统暂停 define PF FSTRANS 0 x00020000 读 写文件系统 define PF KSWAPD 0 x00040000 创建swap define PF SWAPOFF 0 x00080000 清空swap define PF LESS THROTTLE 0 x00100000 内存清空 define PF SYNCWRITE 0 x00200000 我在做一个同步写 define PF BORROWED MM 0 x00400000 我是一个kthread做use mm 3 跟踪标志 unsigned long ptrace define PF PTRACED 0 x00000010 进程正在被跟踪 define PF TRACESYS 0 x00000020 正在跟踪系统调用 4 进程优先级 int prio 优先级 在 0 MAX PRIO 1 之间 MAX PRIO 为 140 其中 0 MAX RT PRIO 1 MAX RP PRIO 为 100 属于实时进程范围 MAX RT PRIO MAX PRIO 为非实时进程 数值越大 优先级越小 5 prio array t array 优先级数组 将进程优先级为序号的数组 实时优先级 unsigned long rt priority rt priority 给出实时优先级 rt priority 1000 给出进程每次获得 CPU 后 可以使用的时间 实时进程优先级可以由系统调用 sys sched setschedule 改变 1 3 进程的创建进程的创建 1 8 让我们不妨亲自看看如何从用户空间创建一个进程 用户空间任务和内核 任务的底层机制是一致的 因为二者最终都会依赖于一个名为 do fork 的函数 来创建新进程 在创建内核线程时 内核会调用一个名为 kernel thread 的函数 参见 linux arch i386 kernel process c 此函数执行某些初始化后会调用 do fork 重庆邮电大学移通学院毕业设计 论文 第 1 章 Linux 进程相关内核代码简要分 析 9 图图 1 1 进程创建进程创建 从图 1 1 中 可以看到 do fork 是进程创建的基础 可以在 linux kernel fork c 内找到 do fork 函数 do fork 函数首先调用 alloc pidmap 该调用会分配一个新的 PID 接下 来 do fork 检查调试器是否在跟踪父进程 如果是 在 clone flags 内设置 CLONE PTRACE 标志以做好执行 fork 操作的准备 之后 do fork 函数还会 调用 copy process 向其传递这些标志 堆栈 注册表 父进程以及最新分配 的 PID 新的进程在 copy process 函数内作为父进程的一个副本创建 此函数能执 行除启动进程之外的所有操作 启动进程在之后进行处理 copy process 内的 第一步是验证 CLONE 标志以确保这些标志是一致的 如果不一致 就会返回 EINVAL 错误 接下来 询问 Linux Security Module LSM 看当前任务是否可 以创建一个新任务 接下来 调用 dup task struct 函数 在 linux kernel fork c 内 这会分配 一个新 task struct 并将当前进程的描述符复制到其内 在新的线程堆栈设置好 后 一些状态信息也会被初始化 并且会将控制返回给 copy process 控制回 到 copy process 后 除了其他几个限制和安全检查之外 还会执行一些常规管 理 包括在新 task struct 上的各种初始化 之后 会调用一系列复制函数来复 重庆邮电大学移通学院毕业设计 论文 第 1 章 Linux 进程相关内核代码简要分 析 10 制此进程的各个方面 比如复制开放文件描述符 copy files 复制符号信息 copy sighand 和 copy signal 复制进程内存 copy mm 以及最终复制线程 copy thread 之后 这个新任务会被指定给一个处理程序 同时对允许执行进程的处理 程序进行额外的检查 cpus allowed 新进程的优先级从父进程的优先级继承后 执行一小部分额外的常规管理 而且控制也会被返回给 do fork 在此时 新 进程存在但尚未运行 do fork 函数通过调用 wake up new task 来修复此问题 此函数 可在 linux kernel sched c 内找到 初始化某些调度程序的常规管理信息 将新进程放置在运行队列之内 然后将其唤醒以便执行 最后 一旦返回至 do fork 此 PID 值即被返回给调用程序 进程完成 1 4 Linux 进程调度进程调度 1 3 8 9 11 1 4 1 总述总述 2 6 调度系统从设计之初就把开发重点放在更好满足实时性和多处理机并 行性上 并且基本实现了它的设计目标 新调度系统的特性为如下几点 1 交互式作业优先 2 轻载条件下调度 唤醒的高性能 3 公平共享 4 基于优先级调度 5 高 CPU 使用率 6 SMP 高效亲和 7 实时调度和 cpu 绑定等调度手段 1 4 2 runqueque 结构结构 1 3 此结构定义在 linux kernel sched c 中 runpuepue 中的 prio arrary t active expired arrays 2 成员说明 此是这个结构中的关键数据结构 每个 重庆邮电大学移通学院毕业设计 论文 第 1 章 Linux 进程相关内核代码简要分 析 11 CPU 队列按照时间片是否用完分为两部分 分别通过 active 和 expired 两个指 针访问 active 指向时间片没用完 当前可被调度的就绪进程 expired 指向时 间片用完的就绪进程 每一个就绪进程都用一个 struct prio array 的结构表示 1 4 3 runqueque 结构分析结构分析 3 1 spinlock t lock runqueue 的自旋锁 当需要对 runqueue 进行操作时 仍然应该锁定 但 这个锁定操作只影响一个 CPU 上的就绪队列 因此 竞争发生的概率要小多 了 2 task t curr 本 CPU 正在运行的进程 3 tast t idle 指向本 CPU 的 idle 进程 相当于 2 4 中 init tasks this cpu 的作用 4 int best expired prio 记录 expired 就绪进程组中的最高优先级 数值最小 该变量在进程进入 expired 队列的时候保存 schedule tick 用途见 expired timestamp 的解释 5 unsigned long expired timestamp 当新一轮的时间片递减开始后 这一变量记录着最早发生的进程耗完时间 片事件的时间 jiffies 的绝对值 在 schedule tick 中赋 它用来表征 expired 中就绪进程的最长等待时间 它的使用体现在 EXPIRED STARVING rq 宏上 上面已经提到 每个 CPU 上维护了两个就绪队列 active 和 expired 一 般情况下 时间片结束的进程应该从 active 队列转移到 expired 队列中 schedule tick 但如果该进程是交互式进程 调度器就会让其保持在 active 队列上以提高它的响应速度 这种措施不应该让其他就绪进程等待过长时间 也就是说 如果 expired 队列中的进程已经等待了足够长时间了 即使是交互 重庆邮电大学移通学院毕业设计 论文 第 1 章 Linux 进程相关内核代码简要分 析 12 式进程也应该转移到 expired 队列上来 排空 active 这个阀值就体现在 EXPIRED STARVING rq 上 在 expired timestamp 和 STARVATION LIMIT 都不等于 0 的前提下 如果以下两个条件都满足 则 EXPIRED STARVING 返回真 1 当前绝对时间 expired timestamp STARVATION LIMIT 队列中 所有就绪进程总数 1 也就是说 expired 队列中至少有一个进程已经等 待了足够长的时间 2 正在运行的进程的静态优先级比 expired 队列中最高优先级要低 best expired prio 数值要大 此时当然应该尽快排空 active 切换到 expired 上来 6 struct mm struct prev mm 保存进程切换后被调度下来的进程 称之为 prev 的 active mm 结构指针 7 unsigned long nr running 本 CPU 上的就绪进程数 该数值是 active 和 expired 两个队列中进程数 的总和 是说明本 CPU 负载情况的重要参数 8 unsigned long nr switches 记录了本 CPU 上自调度器运行以来发生的进程切换的次数 9 unsigned long nr uninterruptible 记录本 CPU 尚处于 TASK UNINTERRUPTIBLE 状态的进程数 和负载 信息有关 10 atomic t nr iowait 记录本 CPU 因等待 IO 而处于休眠状态的进程数 11 unsigned long timestamp last tick 本就绪队列最近一次发生调度事件的时间 在负载平衡的时候会用到 12 int prev cpu load NR CPUS 记录进行负载平衡时各个 CPU 上的负载状态 13 atomic t node nr running int prev node load MAX NUMNODES 这两个属性仅在 NUMA 体系结构下有效 记录各个 NUMA 节点上的就 重庆邮电大学移通学院毕业设计 论文 第 1 章 Linux 进程相关内核代码简要分 析 13 绪进程数和上一次负载平衡操作时的负载情况 14 task t migration thread 指向本 CPU 的迁移进程 每个 CPU 都有一个核心线程用于执行进程迁 移操作 15 struct list head migration queue 需要进行迁移的进程列表 1 5 进程的撤销进程的撤销 3 进程销毁可以通过几个事件驱动 通过正常的进程结束 通过信号或是 通过对 exit 函数的调用 不管进程如何退出 进程的结束都要借助对内核函数 do exit 在 linux kernel exit c 内 的调用 do exit 的目的是将所有对当前进程的引用从操作系统删除 针对所有没有 共享的资源 销毁的过程先要通过设置 PF EXITING 标志来表明进程正在退 出 内核的其他方面会利用它来避免在进程被删除时还试图处理此进程 将进 程从它在其生命期间获得的各种资源分离开来是通过一系列调用实现的 比如 exit mm 删除内存页 和 exit keys 释放线程会话和进程安全键 do exit 函数 执行释放进程所需的各种统计 这之后 通过调用 exit notify 执行一系列通知 比如 告知父进程其子进程正在退出 最后 进程状态被更改为 PF DEAD 并且还会调用 schedule 函数来选择一个将要执行的新进程 请注意 如果对父 进程的通知是必需的 或进程正在被跟踪 那么任务将不会彻底消失 如果无 需任何通知 就可以调用 release task 来实际收回由进程使用的那部分内存 重庆邮电大学移通学院毕业设计 论文 第 2 章 Linux 多进程编程 14 第第 2 章章 Linux 多进程编程多进程编程 2 1 进程的创建进程的创建 1 2 3 7 15 2 1 1 fork 1 3 15 fork 系统调用是随着 UNIX 的诞生一起诞生的 fork 系统调用是众多 UNIX 经典的系统掉用中出类拔萃的一个 几乎所有的 UNIX 及类 UNIX 系统 中都有 fork fork 在英文中的意义为分枝 显而易见 fork 是所有类 UNIX 系 统中最常用的进程创建系统调用 头文件 include include 函数定义 pid t fork void pid t 是一个宏定义 其实质是 int 被定义在 include中 返回值 若成功调用一次则返回两个值 子进程返回 0 父进程返回子进 程 ID 否则 出错返回 1 函数说明 一个现有进程可以调用 fork 函数创建一个新进程 由 fork 创建 的新进程被称为子进程 child process fork 函数被调用一次但返回两次 两次 返回的唯一区别是子进程中返回 0 值而父进程中返回子进程 ID 子进程是父进 程的副本 它将获得父进程数据空间 堆 栈等资源的副本 注意 子进程持 有的是上述存储空间的 副本 这意味着父子进程间不共享这些存储空间 它 们之间共享的存储空间只有代码段 为什么 fork 会返回两次 由于在复制时复制了父进程的堆栈段 所以两个 进程都停留在 fork 函数中 等待返回 因为 fork 函数会返回两次 一次是在父 进程中返回 另一次是在子进程中返回 这两次的返回值是不一样的 实例 fork test c include include 重庆邮电大学移通学院毕业设计 论文 第 2 章 Linux 多进程编程 15 include int child int a 子进程函数 int i for i a i 20 i printf i am the child process d n i sleep 1 if i 6 exit 0 return 0 int main void pid t pid 定义子进程 PID int i pid fork 获得子进程 PID int a 3 if pid 0 printf error in fork n else if pid 0 创建子进程 child 3 子进程代码 else for i 0 i 10 i 父进程代码 printf i am the parent process d n i sleep 1 return 0 程序输出 i am the parent process 0 重庆邮电大学移通学院毕业设计 论文 第 2 章 Linux 多进程编程 16 i am the child process 3 i am the parent process 1 i am the child process 4 i am the parent process 2 i am the child process 5 i am the parent process 3 i am the child process 6 i am the parent process 4 i am the parent process 5 i am the parent process 6 i am the parent process 7 i am the parent process 8 i am the parent process 9 代码关键部分解释 首先 定义子进程的 PID 代码为 pid t pid 再次 获得子进程 PID 代码 pid fork 第三 对于 main 函数中的 if 语句 if pid 0 如果 pid 0 子进程创建错误 else if pid 0 当 pid 0 时 此时 else if 中的语句就是子进程代码 else 父进程代码 这里值得注意的是如果 pid 不小于 0 则 else if 和 else 中的代码是同时运 行的 这和一般的 if else if else 语句同 这里还需要注意的是在子进程函数中有个 exit 系统调用 当子进程运行到 exit 时 子进程退出 而父进程不受影响 2 1 2 fork 与与 vfork 区别区别 3 fork 与 vfock 都是创建一个进程 那他们有什么区别呢 总结有以下三 重庆邮电大学移通学院毕业设计 论文 第 2 章 Linux 多进程编程 17 点区别 1 fork 子进程拷贝父进程的数据段 堆栈段 vfork 子进程与父进程共享数据段 2 fork 父子进程的执行次序不确定 vfork 保证子进程先运行 在调用 exec 或 exit 之前与父进程数据是共享 的 在它调用 exec 或 exit 之后父进程才可能被调度运行 3 vfork 保证子进程先运行 在她调用 exec 或 exit 之后父进程才可能被 调度运行 如果在 调用这两个函数之前子进程依赖于父进程的进一步动作 则 会导致死锁 2 2 exec 函数族函数族 1 2 3 15 2 2 1 简介简介 说是 exec 系统调用 实际上在 Linux 中 并不存在一个 exec 的函数形式 exec 指的是一组函数 一共有 6 个 分别是 include int execl const char path const char arg int execlp const char file const char arg int execle const char path const char arg char const envp int execv const char path char const argv int execvp const char file char const argv int execve const char path char const argv char const envp 其中只有 execve 是真正意义上的系统调用 其它都是在此基础上经过包装 的库函数 exec 函数族的作用是根据指定的文件名找到可执行文件 并用它来取代调 用进程的内容 换句话说 就是在调用进程内部执行一个可执行文件 这里的 可执行文件既可以是二进制文件 也可以是任何 Linux 下可执行的脚本文件 与一般情况不同 exec 函数族的函数执行成功后不会返回 因为调用进程 的实体 包括代码段 数据段和堆栈等都已经被新的内容取代 只留下进程 ID 等一些表面上的信息仍保持原样 看上去还是旧的躯壳 却已经注入了新的灵 重庆邮电大学移通学院毕业设计 论文 第 2 章 Linux 多进程编程 18 魂 只有调用失败了 它们才会返回一个 1 从原程序的调用点接着往下执行 现在我们应该明白了 Linux 下是如何执行新程序的 每当有进程认为自 己不能为系统和拥护做出任何贡献了 他就可以发挥最后一点余热 调用任何 一个 exec 让自己以新的面貌重生 或者 更普遍的情况是 如果一个进程想 执行另一个程序 它就可以 fork 出一个新进程 然后调用任何一个 exec 这样 看起来就好像通过执行应用程序而产生了一个新进程一样 2 2 2 exec 函数族解析函数族解析 3 2 2 2 1 execl 执行文件执行文件 相关函数 fork execle execlp execv execve execvp 表头文件 include 定义函数 int execl const char path const char arg 函数说明 execl 用来执行参数 path 字符串所代表的文件路径 接下来的参数代表执行该 文件时传递过去的 argv 0 argv 1 最后一个参数必须用空指针 NULL 作 结束 返回值 如果执行成功则函数不会返回 执行失败则直接返回 1 失败 原因存于 errno 中 范例 include main execl bin ls ls al etc passwd char 0 执行 rw r r 1 root root 705 Sep 3 13 52 etc passwd 2 2 2 2 execlp 从从 PATH 环境变量中查找文件并执环境变量中查找文件并执 相关函数 fork execl execle execv execve execvp 表头文件 include 定义函数 int execlp const char file const char arg 重庆邮电大学移通学院毕业设计 论文 第 2 章 Linux 多进程编程 19 函数说明 execlp 会从 PATH 环境变量所指的目录中查找符合参数 file 的文件名 找到后 便执行该文件 然后将第二个以后的参数当做该文件的 argv 0 argv 1 最后一个参数必须用空指针 NULL 作结束 返回值 如果执行成功则函数不会返回 执行失败则直接返回 1 失败原因存于 errno 中 错误代码 参考 execve 范例 执行 ls al etc passwd execlp 会依 PATH 变量中的 bin 找到 bin ls include main execlp ls ls al etc passwd char 0 执行 rw r r 1 root root 705 Sep 3 13 52 etc passwd 2 2 23 execv 执行文件执行文件 相关函数 fork execl execle execlp execve execvp 表头文件 include 定义函数 int execv const char path char const argv 函数说明 execv 用来执行参数 path 字符串所代表的文件路径 与 execl 不同的地方在于 execve 只需两个参数 第二个参数利用数组指针来传递给执行文件 返回值 如果执行成功则函数不会返回 执行失败则直接返回 1 失败原因存 于 errno 中 错误代码 请参考 execve 范例 执行 bin ls al etc passwd include main char argv ls al etc passwd char execv bin ls argv 执行 rw r r 1 root root 705 Sep 3 13 52 etc passwd 2 2 2 4 execve 执行文件执行文件 重庆邮电大学移通学院毕业设计 论文 第 2 章 Linux 多进程编程 20 相关函数 fork execl execle execlp execv execvp 表头文件 include 定义函数 int execve const char filename char const argv char const envp 函数说明 execve 用来执行参数 filename 字符串所代表的文件路径 第二个参数系利用数 组指针来传递给执行文件 argv 要传递给程序的完整参数列表 包括 argv 0 它一般是执行程序的名字 最后一个参数则为传递给执行文件的新环境变量数 组 返回值如果执行成功则函数不会返回 执行失败则直接返回 1 失败原因 存于 errno 中 错误代码 EACCES 1 欲执行的文件不具有用户可执行的权限 2 欲执行的文件所属的文件系统是以 noexec 方式挂上 3 欲执行的文件或 script 翻译器非一般文件 EPERM 1 进程处于被追踪模式 执行者并不具有 root 权限 欲执行的文件具有 SUID 或 SGID 位 2 欲执行的文件所属的文件系统是以 nosuid 方式挂上 欲执行的文件具有 SUID 或 SGID 位元 但执行者并不具有 root 权限 include include include int main void char args bin ls NULL if 1 execve bin ls args NULL perror execve exit EXIT FAILURE puts shouldn t get here exit EXIT SUCCESS root localhost src gcc execve c root localhost src a out a out child fork c execve c fork c getpid c 重庆邮电大学移通学院毕业设计 论文 第 2 章 Linux 多进程编程 21 2 3 进程间通信进程间通信 1 2 3 4 7 2 3 1 总述总述 linux 下的进程通信手段基本上是从 Unix 平台上的进程通信手段继承而来 的 而对 Unix 发展做出重大贡献的两大主力 AT pid t pid char r buf 100 char w buf 4 char p wbuf int r num int cmd memset r buf 0 sizeof r buf memset w buf 0 sizeof r buf p wbuf w buf if pipe pipe fd 0 close pipe fd 0 read strcpy w buf 111 if write pipe fd 1 w buf 4 1 printf parent write over n 重庆邮电大学移通学院毕业设计 论文 第 2 章 Linux 多进程编程 24 close pipe fd 1 write printf parent close fd 1 over n sleep 10 程序输出结果 parent write over parent close fd 1 over read num is 4 the data read from the pipe is 111 管道写端关闭后 写入的数据将一直存在 直到读出为止 向管道中写入数据 向管道中写入数据时 linux 将不保证写入的原子性 管道缓冲区一有空闲 区域 写进程就会试图向管道写入数据 如果读进程不读走管道缓冲区中的数 据 那么写操作将一直阻塞 2 有名管道概述及相关 API 应用 2 1 有名管道相关的关键概念 管道应用的一个重大限制是它没有名字 因此 只能用于具有亲缘关系的 进程间通信 在有名管道 named pipe 或 FIFO 提出后 该限制得到了克服 FIFO 不同于管道之处在于它提供一个路径名与之关联 以 FIFO 的文件形式存 在于文件系统中 这样 即 使与 FIFO 的创建进程不存在亲缘关系的进程 只 要可以访问该路径 就能够彼此通过 FIFO 相互通信 能够访问该路径的进程以 及 FIFO 的创建进程之 间 因此 通过 FIFO 不相关的进程也能交换数据 值 得注意的是 FIFO 严格遵循先进先出 first in first out 对管道及 FIFO 的读总 是从开始处返回数据 对它们的写则把数据添加到末尾 它们不支持诸如 lseek 等文件定位操作 2 2 有名管道的创建 include include int mkfifo const char pathname mode t mode 重庆邮电大学移通学院毕业设计 论文 第 2 章 Linux 多进程编程 25 该函数的第一个参数是一个普通的路径名 也就是创建后 FIFO 的名字 第二个参数与打开普通文件的 open 函数中的 mode 参数相同 如果 mkfifo 的 第一个参数是一个已经存在的路径名时 会返回 EEXIST 错误 所以一般典型 的调用代码首先会检查是否返回该错误 如果确实返回该错 误 那么只要调用 打开 FIFO 的函数就可以了 一般文件的 I O 函数都可以用于 FIFO 如 close read write 等等 2 3 有名管道的打开规则 有名管道比管道多了一个打开操作 open FIFO 的打开规则 如果当前打开操作是为读而打开 FIFO 时 若已经有相应进程为写而打开 该 FIFO 则当前打开操作将成功返回 否则 可能阻塞直到有相应进程为写而 打开该 FIFO 当前打开操作设置了阻塞标志 或者 成功返回 当前打开操作没 有设置阻塞标志 如果当前打开操作是为写而打开 FIFO 时 如果已经有相应进程为读而打 开该 FIFO 则当前打开操作将成功返回 否则 可能阻塞直到有相应进程为读 而打开该 FIFO 当前打开操作设置了阻塞标志 或者 返回 ENXIO 错误 当前 打开操作没有设置阻塞标志 2 4 有名管道的读写规则 从 FIFO 中读取数据 约定 如果一个进程为了从 FIFO 中读取数据而阻塞打开 FIFO 那么称该 进程内的读操作为设置了阻塞标志的读操作 如果有进程写打开 FIFO 且当前 FIFO 内没有数据 则对于设置了阻塞标 志的读操作来说 将一直阻塞 对于没有设置阻塞标志读操作来说则返回 1 当前 errno 值为 EAGAIN 提醒以后再试 对于设置了阻塞标志的读操作说 造成阻塞的原因有两种 当前 FIFO 内 有数据 但有其它进程在读这些数据 另外就是 FIFO 内没有数据 解阻塞的 原因则是 FIFO 中有新的数据写入 不论信写入数据量的大小 也不论读操作 请求多少数据量 重庆邮电大学移通学院毕业设计 论文 第 2 章 Linux 多进程编程 26 读打开的阻塞标志只对本进程第一个读操作施加作用 如果本进程内有多 个读操作序列 则在第一个读操作被唤醒并完成读操作后 其它将要执行的读 操作将不再阻塞 即使在执行读操作时 FIFO 中没有数据也一样 此时 读操 作返回 0 如果没有进程写打开 FIFO 则设置了阻塞标志的读操作会阻塞 向 FIFO 中写入数据 约定 如果一个进程为了向 FIFO 中写入数据而阻塞打开 FIFO 那么称该 进程内的写操作为设置了阻塞标志的写操作 对于设置了阻塞标志的写操作 当要写入的数据量不大于 PIPE BUF 时 linux 将保证写入的原子性 如果 此时管道空闲缓冲区不足以容纳要写入的字节数 则进入睡眠 直到当缓冲区 中能够容纳要写入的字节数时 才开始进行一次性写操作 当要写入的数据量大于 PIPE BUF 时 linux 将不再保证写入的原子性 FIFO 缓冲区一有空闲区域 写进程就会试图向管道写入数据 写操作在写完所 有请求写的数据后返回 对于没有设置阻塞标志的写操作 当要写入的数据量大于 PIPE BUF 时 linux 将不再保证写入的原子性 在 写满所有 FIFO 空闲缓冲区后 写操作返回 当要写入的数据量不大于 PIPE BUF 时 linux 将保证写入的原子性 如果 当前 FIFO 空闲缓冲区能够容纳请求写入的字节数 写完后成功返回 如果当 前 FIFO 空闲缓冲区不能够容纳请求写入的字节数 则返回 EAGAIN 错误 提 醒以后再写 对 FIFO 读写规则的验证 下面提供了两个对 FIFO 的读写程序 适当调节程序中的很少地方或者程 序的命令行参数就可以对各种 FIFO 读写规则进行验证 程序 1 写 FIFO 的程序 include include include 重庆邮电大学移通学院毕业设计 论文 第 2 章 Linux 多进程编程 27 include define FIFO SERVER tmp fifoserver main int argc char argv 参数为即将写入的字节数 int fd char w buf 4096 2 int real wnum memset w buf 0 4096 2 if mkfifo FIFO SERVER O CREAT O EXCL 0 if fd 1 if errno ENXIO printf open error no reading process n fd open FIFO SERVER O WRONLY O NONBLOCK 0 设置非阻塞标志 fd open FIFO SERVER O WRONLY 0 设置阻塞标志 real wnum write fd w buf 2048 if real wnum 1 if errno EAGAIN printf write to fifo error try later n else printf real write num is d n real wnum real wnum write fd w buf 5000 5000 用于测试写入字节大于 4096 时的非原子性 real wnum write fd w buf 4096 4096 用于测试写入字节不大于 4096 时的原子性 if real wnum 1 if errno EAGAIN printf try later n 程序 2 与程序 1 一起测试写 FIFO 的规则 第一个命令行参数是请求从 FIFO 读出的字节数 重庆邮电大学移通学院毕业设计 论文 第 2 章 Linux 多进程编程 28 include include include include define FIFO SERVER tmp fifoserver main int argc char argv char r buf 4096 2 int fd int r size int ret size r size atoi argv 1 printf requred real read bytes d n r size memset r buf 0 sizeof r buf fd open FIFO SERVER O RDONLY O NONBLOCK 0 fd open FIFO SERVER O RDONLY 0 在此处可以把读程序编译成两个不同版本 阻塞版本及非阻塞版本 if fd 1 printf open s for read error n exit while 1 memset r buf 0 sizeof r buf ret size read fd r buf r size if ret size 1 if errno EAGAIN printf no data avlaible n printf real read bytes d n ret size sleep 1 pause unlink FIFO SERVER 程序应用说明 把读程序编译成两个不同版本 阻塞读版本 br 以及非阻塞读版本 n
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 呼吸系统营养治疗
- 护理工作创新
- 散货货代专业知识培训课件
- 散文标题探究课件
- 敏捷知识点培训方案课件
- 远程医疗在2025年偏远地区医疗服务中的远程医疗质量控制研究
- 隧道施工作业指导书
- 畜牧业信息化竞争力-洞察及研究
- 机械工程师岗位述职报告范文
- 零售店铺促销活动效果评估方法
- 心肺复苏术课件2024新版
- 大厦消防工程技术标
- 水中总氯的测定方法确认实验报告(HJ586)
- GB/T 1228-2006钢结构用高强度大六角头螺栓
- 第二章-基因工程的载体和工具酶课件
- 政府采购评审专家考试题库(含答案)
- 实验室新员工入职培训课件
- 动力柜技术协议
- 2023年青岛市城阳区工会系统招聘考试笔试题库及答案解析
- 高中生物第一课-(共24张)课件
- 电气原理图基础知识课件
评论
0/150
提交评论