Linux应用编程基础学习_第1页
Linux应用编程基础学习_第2页
Linux应用编程基础学习_第3页
Linux应用编程基础学习_第4页
Linux应用编程基础学习_第5页
已阅读5页,还剩10页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Linux 下开发基础知识 touch 命令 :可用于新建文件,如 ; touch /tmp/zhangxian.txt 关于 v0latile 的介绍 ( 类型修饰符,指令关键字 ) 1. 编译器优化介绍 由于内存访问速度远不及 CPU 处理速度,为提高机器整体性能,在硬件上引入硬件高速缓 存 Cache ,加速对内存的访问。 另外在现代 CPU 中指令的执行并不一定严格按照顺序执行, 没有相关性的指令可以乱序执行,以充分利用 CPU 的指令流水线,提高执行速度。以上是 硬件级别的优化。 再看软件一级的优化: 一种是在编写代码时由程序员优化, 另一种是由编 译器进行优化。 编译器优化常用的方

2、法有: 将内存变量缓存到寄存器; 调整指令顺序充分利 用 CPU 指令流水线,常见的是重新排序读写指令。对常规内存进行优化的时候,这些优化 是透明的, 而且效率很好。 由编译器优化或者硬件重新排序引起的问题的解决办法是在从硬 件(或者其他处理器)的角度看必须以特定顺序执行的操作之间设置内存屏障(mem0ry barrier ), Iinux 提供了一个宏解决编译器的执行顺序问题。 CPU 寄存 2. v0id Barrier(v0id) 这个函数通知编译器插入一个内存屏障,但对硬件无效,编译后的代码会把当前 器中的所有修改过的数值存入内存,需要这些数据的时候再重新从内存中读出。 3. v0Ia

3、tiIe 总是与优化有关 ,编译器有一种技术叫做数据流分析,分析程序中的变量在哪里 赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可 以消除一些代码。但有时这些优化不是程序所需要的,这时可以用v0IatiIe 关键字禁止做这 些优化。 gcc and g+ 分别是 GNU 的 c 2. 将预处理后的文件转换成汇编语言,生成文件.S编译器egcs; 3. 由汇编变为目标代码(机器代码)生成 .0的文件汇编器as; 4连接目标代码,生成可执行程序链接器Id; gcc 编译流程分为 4 个步骤,分别为: 预处理( Pre-Pr0cessing ) 编译( c0mpiI

4、ing ) 汇编( AssembIing ) 链接( Linking ) source code Pre-Pro cessing gcc-E helloworld.c-o helloworld.i Com piling gcc -5 helloworidJ -o helloworld,5 Assembling f Linking executable gcc -c helloworld.s -o heHoworld-o gcc helloworJd.o -o helloworld g+ -o -c -g 功能 -o :指定生成可执行文件的名称。使用方法为:g+-0 afile file.cpp

5、 file.h .(可执行文件 不可与待编译或链接文件同名,否则会生成相应可执行文件且覆盖原编译或链接文件),如 a.out。 果不使用-o选项,则会生成默认可执行文件 -c :只编译不链接,只生成目标文件。 -g :添加gdb调试选项。 Linux下C语言应用编程 1. 2. 3. 4. 5. 6. 文件I/O编程 多进程编程的基本知识,核心是fork、exec、wait三大系统的调用;(可能需要补充操作 系统进程并发运行的基本知识) 进程间通信的几种方法: 和管道) 多线程编程的基础知识; 网络编程:socket编程, 开发工具(包括:编辑器 库的制作等); 编译器vim的三种模式: 信号

6、,管道,共享内存,信号量, TCP socket 编程和 UDP socket vim、编译器gcc、调试器gdb、 消息队列。(最重要的是信号 编程; 工程管理工具autoconf、程序 1.切换到编辑模式的四种方式,编辑模式可以输入任意内容 光标向后移动一位 当前位置 另起新行 删除光标所在字符 替换光标所在字符 2.尾行模式,用于保存内容、查找替换、设置行号等等功能性操作 /quit退出vi编辑器 /write 保存修改的内容 /保存并退出 :wq :q! /强制退出,当对文本内容作了修改而不想要保存时 :w! /强制保存,当没有文本的写权限时 make 禾口 makefile 文件:

7、:q makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些 文件需要重新编译,甚至于进行更复杂的功能操作(因为makefile就像一个Shell脚本一 样,可以执行操作系统的命令)。makefile带来的好处就是一“自动化编译”,一旦写 好,只需要一个 make命令,整个工程完全自动编译。makefile文件需要按照某种语法进 行编写,文件中需要说明如何编译各个源文件并链接生成可执行文件,要求定义源文件之 间的依赖关系。 make工具最主要也最基本的功能就是根据makefile文件中描述的源程序之间的相互关系 来完成自动编译、维护多源文件工程。 Linux下

8、的常用命令 Linux删除文件夹和文件的命令 -r就是向下递归,不管有多少级目录,一并删除 -f就是直接强行删除,不作任何提示的意思 删除文件夹实例: rm -rf /var/log/htt pd/access 将会删除/var/log/httpd/access目录以及其下所有文件、文件夹 删除文件使用实例: rm -f /var/log/htt pd/access .log 将会强制删除/var/log/httpd/access.log这个文件 文件I/O编程: 系统调用、API与系统命令之间的关系 Linux系统调用是指操作系统提供给用户程序的一组“特殊”接口,用户程序 可以通过这组“特殊

9、”接口来获得操作系统内核提供的特殊服务。比如用户可 以通过文件系统相关的调用请求系统打开文件、关闭文件或读写文件,可以通 过时钟相关的系统调用获得系统时间或设置系统时间等。 为了更好的保护内核空间,将 程序的运行空间分为内核空间和用户空间,它们 运行在不同的级别上,在逻辑上是相互隔离的。在Linux中,用户程序不能直 接访问内核提供的服务,必须通过 系统调用来使用内核提供的服务。用户进程 在通常情况下不允许访问内核数据,也无法使用内核函数,它们只能在用户空 间操作用户数据,调用用户空间函数。 Linux 中的用户编程接口( API )遵循了 UNIX 中最流行的 应用编程界面标准 - POSI

10、X 标准。(这些系统调用编程接口主要是通过 C 库( libc )实现的。)这 套标准定义了一系列 API。在Linux中(Unix也如此)这些API主要是通过C 库( libc )实现的,它除了定义的一些标准的 是提供了一套 封装例程( wrapper routine ) 户编程使用。 C 函数外,一个很重要的任务就 将系统调用在用户空间包装后供用 读文件、写文件等。大多数 Linux 5 个函数:open read write、lseek 以及 closeo 这 5 个函 函数,它们是 POSIX 标准的组成部分 。 可用的文件 I/O 函数很多,包括:打开文件、 文件 I/O 只需要用到

11、 数是不带缓存的 I/O 在 C 语言中也有文件 函数是带缓存的 I/O 函数,它们属于 ANSI C 的组成部分 。 I/O 函数,例如: fread、 fwrite 、fprintf 、 fscanf 等。这些 Linux下系统调用、API、系统命令、内核函数的区别与联系 1. 系统调用:应用程序和内核间的桥梁, 是应用程序访问内核的入口点 ; 但通常情况下, 应用程序通过操作系统提供的 API 进行编程而不是使用系统调用直接编程 ; linux 的全部系统调用加起来大约只有250个左右。 这些系统调用按照功能逻辑大致可分为“进程控制”、“文件系统控制”、“系统 控制”、“存管管理”、 “

12、网络管理”、 “socket 控制 ”、“用户管理 ”、“进程间通信 ” 几类; 可以使用 man 2 syscalls 命令查看系统调用的说明 ,或者到 源文件种找到它们的原本。 录 /in clude/asm-i386/uni std.h 1.系统调用在内核里的主要用途: 管理 内核源码目 控制硬件;设置系统状态或读取内核数据;进程 或者说什么功能应该在内核而不是在用户空间; (如 2.什么的服务应该存在于内核, 服务是否必须获得内核数据;安全的角度;效率的角度等) 2. API: API常以C库(libc)的形式提供,C库提供了绝大部分 API,每个系统调用在 C 库中都有对应的封装函数

13、 (通常封装函数与系统调用的名称相同 )。系统调用与 C 库函数并不是一一对应的,有些C库函数可能使用多个系统调用来实现,也有可能 多个 C 库函数使用同一个系统调用来实现, 实现。 也有些 C 库函数不使用任何系统调用来 3. 系统命令: 系统命令是 使用 Linux 提供的 C 库函数实现的可执行程序 ,可用 strace 查看命令执行时所使用的系统调用。 4. 内核函数: 系统调用是用户进入内核的接口, 它本身不是内核函数,进入内核后每 个系统调用会找到自己对应的内核函数 (即系统调用服务例程 ) 从用户的角度看,从底层往上看分别是:内核函数,系统调用, API,系统命令 内核函数和系统

14、调用的关系 :内核函数和普通函数很像,只不过在内核中实现,因此要满 足一些内核编程的要求。系统调用是一层用户进入内核的接口,它本身并非内核函数,进 入内核后,不同的系统调用会找到对应到各自的内核函数即,系统调用服务例程。实际对 请求服务的是内核函数而非调用接口(系统调用)。比如系统调用 核函数 sys_getpid 。 getpid 实际就是调用内 Linux 下不带缓存的 I/O 和带缓存的 I/O : 概念: 不带缓存的 I/O : UNIX 的文件 I/O read、 write 是不带缓存的,不带缓存是指每个 一个系统调用,它们是 POSIX.1 的组成部分。不是内核不提供缓存, 没有

15、提供缓存,而对内核来说还是有缓存的 read 、write 都调用内核的 而是对于用户层来说, 数据:数据流 - 内核缓存 - 磁盘 带缓存的 I/O : 是指在用户层上再建立了一层缓存区 (流缓存区) ,目的是为了减少 read ,write 等系统调用 的使用次数,降低系统开销。带缓存的 I/O 是指标准 I/O 库,它由 ANSI C 标准说明,标准 I/O 库代替用户处理很多细节,比如缓存分配、以优化长度执行 I/O 等,提供缓存的目的是 为了尽量减少 read 和 write 的调用次数; 数据:数据流 - 流缓存区 - 内核缓存 - 磁盘 例如:当用 fwrite 函数向磁盘写数据

16、时,先把数据写入流缓冲区中,当达到一定条件,比如 流缓冲区满了, 或刷新流缓冲, 这时候才会把数据一次送往内核提供的块缓冲, 再经块缓冲 写入磁盘。(双重缓冲) 用数据流来形容两者的差异: 无缓存 I/O 操作的数据流:数据 - 内核缓存区 - 磁盘 标准 I/O 操作的数据流:数据 - 流缓存区 - 内核缓存区 - 磁盘 文件描述符 对内核而言, 所有打开文件都由文件描述符应用。 文件描述符是一个非负整数。 当打开一个 现存文件或创建一个新文件时,内核向进程返回一个文件描述符。 当读、写一个文件时,用 open 或 create 返回的文件描述符标识该文件,将其作为参数传送 给 read 或

17、 write 。在 windows 环境下,文件描述符大体上相当于文件句柄。 在P0SIX.1应用程序中,整数 0、1、2应被代换成符号常数: STDIN_FILENO 代表标准输入(默认是键盘) 、标准输出(默认是屏幕) 、标准错误输出(默 认是屏幕),这些常数都定义在头文件 中。 多进程编程 进程是一个具有一定独立功能的程序对某个数据集合的一次运行活动。进程的实体结构: 1. 进程控制块( PCB) ; 2. 程序段; 3. 数据段; PCB位于内核的内存里面的一块区域,是操作系统中最重要的记录型数据结构。PCB中记录 了操作系统所需的,用于描述进程进展情况及控制进程所需的全部信息。 进程

18、块主要包括下述 4 方面的信息: 进程描述信息 处理机状态信息 进程调度信息: 进程状态 、进程优先级 (用于描述进程使用处理机的优先级别的一 个整数,优先级别高的进程先获得处理机) 、 进程调度所需的其他信息 (如进程已 等待 CPU 的时间总和、 进程已执行的时间总和等) 、事件(指进程被阻塞的原因) 。 进程控制信息: 程序和数据的地址 (指出该进程的程序和数据所在的内存或外存地 址,以便再调度到该进程执行时,能从中找到其程序和数据);进程同步和通信机 制(指实现进程同步和进程通信时所必须的机制,如消息队列指针、信号量等。这 些数据应全部或部分存放在 1. 2. 3. 4. PCB 中)

19、。 进程的三种状态: 图2”5进粹肘二种皋本狀态朋其转换 进程的三种基本状态: (1) 就绪状态:进程已获得除 CPU外的所有必要资源,只等待 CPU时的状态。一个系统 会将多个处于就绪状态的进程排成一个就绪队列。 (2) 执行状态:进程已获CPU,正在执行。单处理机系统中,处于执行状态的进程只一个; 多处理机系统中,有多个处于执行状态的进程。 (3)阻塞状态:正在执行的进程由于某种原因而暂时无法继续执行,便放弃处理机而处于 暂停状态,即进程执行受阻。(这种状态又称等待状态或封锁状态) 通常导致进程阻塞的典型事件有:请求I/O,申请缓冲空间等。 进程间通信 进程间通信有如下一些目的: 数据传输

20、 共享数据 通知事件 资源共享的同步 进程控制 1. 2. 3. 5. 4. 多线程编程初步 线程是一个 程序内部 可以被操作系统调度并发运行的任务。 在很多情况下,完成相关任务的不同代码间需要交换数据。如果采用多进程的方式,那么通 信就只能采用几种进程间通信的方式,但无论是信号、管道、共享内存,还是信号量,它们 的操作都比较繁杂,不直观;而且大多数要使用内核对象,数据要在用户空间和内核空间进 行切换,开销很大。 但如果采用多线程方式,线程间的通信(数据交换)既直观又效率高,例如可以使用共享的全 局变量。 30 倍左右,当然,在具体的 和进程相比, 线程是一种“节俭”的多任务操作方式 。运行于

21、一个进程中的多个线程,它们彼 此之间使用相同的地址空间, 共享大部分数据 ,启动一个线程所花费的空间远小于启动一个 进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需的时间。 (据统计,总的来说,一个进程的开销大约是一个线程开销的 系统上,这个数据可能会有较大的区别) 常用的线程函数 1. 创建线程 : pthread_create (void*)(*start_rtn)(void*),void int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, *arg); 若线程创建成功, 则返回 0。若线程

22、创建失败, 则返回出错编号, 定义的。 返回成功时,由 tidp 指向的内存单元被设置为新创建线程的线程 start_rtn 函数的地址开始运行,该函数只有一个万能 并且 *thread 中的内容是未 ID。 attr参数用于指定各 种不同的线程属性。新创建的线程从 指针参数 arg ,如果需要向 start_rtn 函数传递的参数不止一个, 个结构中,然后把这个结构的地址作为 linux下用C语言开发多线程程序,Linux系统下的多线程遵循POSIX线程接口,称为pthread 。 那么需要把这些参数放到一 arg 的参数传入。 参数 第一个参数为指向线程标识符的指针。 第二个参数用来设置线

23、程属性。 第三个参数是线程运行函数的起始地址。 最后一个参数是运行函数的参数。 当线程运行函数的参数不止一个时, 那么需要把这些 参数放到一个结构中,然后将找个结构的地址当作参数传输参数。 2. 线程互斥锁的初始化 pthread_mutex_init int pthread_mutex_init (pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_init() 函

24、数是以动态方式创建互斥锁的, 参数 attr 指定了新建互斥锁的属 性。 如果参数 attr 为空,则使用默认的互斥锁属性,默认属性为快速互斥锁。互斥锁的属 性在创建锁的时候指定,在 LinuxThreads 实现中仅有一个锁类型属性,不同的锁类型在试 图对一个已经被锁定的互斥锁加锁时表现不同。 3线程初始化条件变量函数pthread_cond_init (); extern int pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t *cond_attr); 其中 cond 是一个指向结构 pthread_co

25、nd_t 的指针, cond_attr 是一个指向结构 pthread_condattr_t 的指针。 结构 pthread_condattr_t 是条件变量的属性结构,和互斥锁一样我们可以用它来设置条件变 量是进程内可用还是进程间可用,默认值是PTHREAD PROCESSPRIVATE,即此条件变量 被同一进程内的各个线程使用;如果选择为P THREADPROCESS_SHARED则为多个进程间 各线程公用。 注意初始化条件变量只有未被使用时才能重新初始化或被释放。 返回值:函数成功返回 0;任何其他返回值都表示错误。 释放一个条件变量的函数为 pthread_cond_ destroy

26、( pthread_cond_t *cond )。 3. 4. 5. 结束线程: pthread_exit / 线程自行结束(自杀)使用 pthread_exit 等待线程结束: pthread_join pthread_create 调用成功后,新生成的线程和老线程谁先被调度执行,取决于OS,应 用程序无法控制。因此,应用程序员如需等待指定线程结束,需要使pthread_join 。 int pthread_join(pthread_t th, void * thread_return); th 是要等待结束的线程的标识。 指针 thread_return 指向的位置存放的是终止线程的返回状

27、态。 sched_yield() 这个函数可以使另一个级别等于或高于当前线程的线程先运行。如果没有 符合条件的线程,那么这个函数将会立刻返回,然后继续执行当前线程的程序。 在成功完成之后返回零,否则返回 -1. 多线程的同步与互斥 由于多个线程间极有可能回访问共享的资源(典型的是访问同一个全局变量) 程间存在竞争,这就需要在多个线程间进行同步。 ,因此多个线 互斥锁 多线程的同步采用加锁的机制, 类似于多进程间的信号量机制。 在主线程中初始化锁为解锁 状态(类似于初始化 0-1 信号量为 1) 1. 在编译时初始化锁为解锁状态; 2. 3. 在访问共享对象前进行加速操作(类似于对信号量执行 在

28、访问共享对象后进行解锁操作(类似于对信号量执行 P 操作); V 操作); void pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); int pthread_attr_setschedparam(pthread_attr_t *restrict attr,const struct sched_param *restrict param); pthread_attr_setinheritesched()用于确定如何设置线程的调度属性,可以从创建者线程或 从一个属性对象来继承调度属性。 inheritsched 可以为如

29、下值: PTHREAD_INHERIT_SCHED :线程调度属性是从创建者线程继承得到, attr 的任何调度属性 都被忽略。 PTHREAD_EXPLICIT_SCHED: 线程调度属性设置为属性对象attr 的调度属性。 如果 inheritsched 值是 PTHREAD_EXPLICIT_SCHED 贝U pthread_attr_setschedpolicy()被用于 设置调度策略,而 pthread_attr_setschedparam( ) 被用于设置优先级。 pthread_attr_setschedpolicy( )设置线程属性对象attr 的调度策略。policy 的值可以为在 头文件中定义的以下值。 SCHED_FIFO先进先出调度策略,执行线程运行到结束。 SCHED_RR轮询调度策略,按照时间片将每个线程分配到处理器上。 SCHED_OTHER另外的调度策略(根据实现定义)。这是任何新创建线程的默认调度策略

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论