Linux环境编程--基础知识

所有操作系统都为他们所运行的程序提供服务,典型的服务包括:执行新程序,读文件,分配存储区以及获取当前时间等。从严格意义来说我们我们可以将操作系统定义为一个软件,他控制计算机硬件资源,提供程序运行环境,由于较小并且位于环境的核心,我们一称为内核
内核的接口被称作系统调用,公用函数库构建在系统调用之上,应用函数既可以使用公用库函数也可以使用系统调用

输入和输出

文件描述符通常是一个很小的非负证书,内核用以表示一个特定的进程正在访问的文件,当内核打开一个现有文件或创建一个新文件的时候,它都返回一个文件描述符,在读和写的时候使用该描述符。而一个程序中最多打开65535个文件描述符。
标准输入,标准输出和标准错误是按照惯例当我们运行一个新程序的时候,shell默认会帮我们打开的三个文件,一般来说标准输入的描述符是0,标准输出的描述符是1,标准错误的描述符是2.为了代码的可读性,我们用STDIN_FILNO,STDOUT_FILENO和STDERR_FILNO来代替描述符中的0,1,2。
当然我们也可以将这三个文件关闭然后打开新的文件,这个时候内核会寻找最小的描述符然后找到这三个文件的描述符并且将这个描述符分配给新文件,这叫做文件重定向。
不带缓冲的IO:函数open,read,write,lseek以及close提供了不带缓冲的IO,用文件描述符。
标准IO标准IO为不带缓冲的IO提供了一个带缓冲的接口,同时我们也可以自己定义缓冲区的大小。

阻塞与非阻塞

所有的IO系统调用默认都是阻塞的,阻塞就是说当进行系统调用的时候, 除非出错或者被信号打断,进程会一直陷入内核态直到调用完成,非阻塞的系统调研是说无论IO是否成功都立刻返回。

同步与异步

同步IO就是说为了完成一个功能,发起调用,如果当前不具备条件就一直等待,直到完成后返回,异步IO就是说为了完成一个功能,发起调用。如果当前不具备条件就直接返回,具备条件了就通过信号或者其他方式来通知
同步异步与阻塞非阻塞的区别在于同步异步关心发起调用后是否立即执行而阻塞与非阻塞关心是否立即返回。

程序和进程

程序是一个存储在磁盘上某个目录上的可执行文件,内核使用exec函数族将程序读入内存,并执行
进程是程序的执行实例为了保证我们进程的独特性每一个进程都有唯一的一个数字标识符,称为进程ID,进程ID一定是一个非负整数。我们一般用getpid得到进程ID
进程控制主要有三种函数第一个是fork函数类,一般用于创建一个进程,第二个是exec函数类,这个函数类中有七个函数,都用于进程的替换,第三个是waitpid函数,用于进程等待。

程序的构成

linux下二进制可执行程序的格式一般为ELF格式,一般有以下段构成:

  1. debug段:用于保存调试信息
  2. dynamic段:用于保存动态链接信息
  3. fini段:用于保存进程退出时候的执行程序,当进程结束的时候会执行此段
  4. init段:用于保存进程启动的执行信息,当进程启动的时候执行此段
  5. data段:数据段,保存非零初始值的全局变量和静态变量
  6. text段:代码段,保存可执行指令
  7. bss段:保存未初始化变量,并不占用物理内存

程序的运行

当我们用gcc生成一个可执行程序的时候,它内部是怎么从一堆代码变成可执行程序的呢
首先我们进行了预处理,预处理就是处理预处理命令,例如宏替换,展开头文件等,这里要注意的是不能在头文件中定义全局变量,不然展开的时候会造成冲突,接下来会进行编译,这里编译器对代码进行语法检测并且优化产生汇编代码,然后是汇编,汇编就是将源代码翻译成可执行的指令并且生成目标文件。最后一步是链接,将各个目标文件链接生成一个可执行文件。

线程和线程ID

线程与进程不同,线程是进程中的一条执行流,一个进程又被叫做一个线程组,一个进程中包含一个或多个线程。可以看出在linux下线程就是轻量级线程。
一个进程内所有线程共享一个地址空间,文件描述符,栈以及进程相关属性。因为他们可以访问同一个存储区所以这里就会有线程安全的问题

线程安全

原子操作是指这个操作是不能被打断的,当我们进行线程间通信的时候通常会发生很多操作打断当前操作,但是如果当前操作是原子操作的话那么这个操作不可分割,不会有任何的中间状态。
在线程间通信的时候由于他们共享一个地址空间等相关属性,所以就有可能发生同时很多线程操作同一个临界资源的情况,这里我们通过同步与互斥操作来保证线程安全,具体行为有设置条件变量,加锁等操作。

线程ID

与进程相同,线程也有自己的唯一标识ID,但是线程ID只在自己的进程内起作用,同时线程组的首线程ID等同于线程组ID同时也是这个进程的进程ID,当我们在另一个进程内引用当前进程中的线程ID是没有意义的。

用户标识

用户ID口令文件登录项中的用户ID是一个数值,向系统标识各个不同的用户,系统在确定一个用户登录名的同时确定登陆ID,用户不能更改ID,每一个用户只能有一个用户ID,用户ID为0的用户是根用户或者叫做超级用户在口令文件中,通常有一个登录项,其登录名是root,某些系统操作功能只向超级用户提供,对系统有自由的支配权。
组ID口令文件登录项也包括用户的组ID,他是一个数值,组ID是由系统管理员在指定用户登陆名时分配的,一般来说在口令文件中多个登录项具有相同的组ID,一个组之间的用户被允许共享资源等,组文件通常是/etc/grep
对于磁盘上的每一个文件,都存储着这个文件的所有者用户ID与组ID
附属组ID除了在口令文件中对一个登录名指定一个组ID之外,还允许一个用户属于另一些组,一个用户最多允许属于十六个其他的组。

功能测试宏

头文件中顶一个很多POSIX和XSI符号,但是除了POSIX和XSI之外,大多数实现在这些头文件中也加入了自己的定义,如果在编译一个程序的时候如果希望只与POSIX定义有关,而不与任何实现定义的常量冲突,那么就需要定义常量_POSIX_C_SOURCE,可以排除任何专有的定义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值