Linux下的C编程实战(4)

标志
 含义
 
r, rb
 以只读方式打开
 
w, wb
 以只写方式打开。如果文件不存在,则创建该文件,否则文件被截断
 
a, ab
 以追加方式打开。如果文件不存在,则创建该文件
 
r+, r+b, rb+
 以读写方式打开
 
w+, w+b, wh+
 以读写方式打开。如果文件不存在时,创建新文件,否则文件被截断
 
a+, a+b, ab+
 以读和追加方式打开。如果文件不存在,创建新文件
 

其中b用于区分二进制文件和文本文件,这一点在DOS、Windows系统中是有区分的,但Linux不区分二进制文件和文本文件。

读写

C库函数支持以字符、字符串等为单位,支持按照某中格式进行文件的读写,这一组函数为:

int fgetc(FILE *stream);

int fputc(int c, FILE *stream);

char *fgets(char *s, int n, FILE *stream);

int fputs(const char *s, FILE *stream);

int fprintf(FILE *stream, const char *format, ...);

int fscanf (FILE *stream, const char *format, ...);

size_t fread(void *ptr, size_t size, size_t n, FILE *stream);

size_t fwrite (const void *ptr, size_t size, size_t n, FILE *stream);

fread()实现从流stream中读取加n个字段,每个字段为size字节,并将读取的字段放入ptr所指的字符数组中,返回实际已读取的字段数。在读

取的字段数小于num时,可能是在函数调用时出现错误,也可能是读到文件的结尾。所以要通过调用feof()和ferror()来判断。

write()实现从缓冲区ptr所指的数组中把n个字段写到流stream中,每个字段长为size个字节,返回实际写入的字段数。

另外,C库函数还提供了读写过程中的定位能力,这些函数包括

int fgetpos(FILE *stream, fpos_t *pos);

int fsetpos(FILE *stream, const fpos_t *pos);

int fseek(FILE *stream, long offset, int whence);

等。

关闭

利用C库函数关闭文件依然是很简单的操作:

int fclose (FILE *stream);

例程:将第2节中的例程用C库函数来实现。

#include <stdio.h>

#define LENGTH 100

main()

{

FILE *fd;

char str[LENGTH];

fd = fopen("hello.txt", "w+"); /* 创建并打开文件 */

if (fd)

{

fputs("Hello, Software Weekly", fd); /* 写入Hello, software weekly字符串 */

fclose(fd);

}

fd = fopen("hello.txt", "r");

fgets(str, LENGTH, fd); /* 读取文件内容 */

printf("%s"n", str);

fclose(fd);

}

4.小结

Linux提供的虚拟文件系统为多种文件系统提供了统一的接口,Linux的文件编程有两种途径:基于Linux系统调用;基于C库函数。这两

种编程所涉及到文件操作有新建、打开、读写和关闭,对随机文件还可以定位。本章对这两种编程方法都给出了具体的实例。

Linux下的C编程实战(三)

――进程控制与进程通信编程


1.Linux进程

Linux进程在内存中包含三部分数据:代码段、堆栈段和数据段。代码段存放了程序的代码。代码段可以为机器中运行同一程序的数个

进程共享。堆栈段存放的是子程序(函数)的返回地址、子程序的参数及程序的局部变量。而数据段则存放程序的全局变量、常数以及动态数

据分配的数据空间(比如用malloc函数申请的内存)。与代码段不同,如果系统中同时运行多个相同的程序,它们不能使用同一堆栈段和数据

段。

Linux进程主要有如下几种状态:用户状态(进程在用户状态下运行的状态)、内核状态(进程在内核状态下运行的状态)、内存中就绪(进程

没有执行,但处于就绪状态,只要内核调度它,就可以执行)、内存中睡眠(进程正在睡眠并且处于内存中,没有被交换到SWAP设备)、就绪

且换出(进程处于就绪状态,但是必须把它换入内存,内核才能再次调度它进行运行)、睡眠且换出(进程正在睡眠,且被换出内存)、被抢

先(进程从内核状态返回用户状态时,内核抢先于它,做了上下文切换,调度了另一个进程,原先这个进程就处于被抢先状态)、创建状态(

进程刚被创建,该进程存在,但既不是就绪状态,也不是睡眠状态,这个状态是除了进程0以外的所有进程的最初状态)、僵死状态(进程调用

exit结束,进程不再存在,但在进程表项中仍有记录,该记录可由父进程收集)。

下面我们来以一个进程从创建到消亡的过程讲解Linux进程状态转换的“生死因果”。

(1)进程被父进程通过系统调用fork创建而处于创建态;

(2)fork调用为子进程配置好内核数据结构和子进程私有数据结构后,子进程进入就绪态(或者在内存中就绪,或者因为内存不够而在SWAP设

备中就绪);

(3)若进程在内存中就绪,进程可以被内核调度程序调度到CPU运行;

(4)内核调度该进程进入内核状态,再由内核状态返回用户状态执行。该进程在用户状态运行一定时间后,又会被调度程序所调度而进入内核

状态,由此转入就绪态。有时进程在用户状态运行时,也会因为需要内核服务,使用系统调用而进入内核状态,服务完毕,会由内核状态转回

用户状态。要注意的是,进程在从内核状态向用户状态返回时可能被抢占,这是由于有优先级更高的进程急需使用CPU,不能等到下一次调度时

机,从而造成抢占;

(5)进程执行exit调用,进入僵死状态,最终结束。

2.进程控制

进程控制中主要涉及到进程的创建、睡眠和退出等,在Linux中主要提供了fork、exec、clone的进程创建方法,sleep的进程睡眠和exit的进程

退出调用,另外Linux还提供了父进程等待子进程结束的系统调用wait。

fork

对于没有接触过Unix/Linux操作系统的人来说,fork是最难理解的概念之一,它执行一次却返回两个值,完全“不可思议”。先看下面的程序

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/1886398572ec6070cfe1e70d62001701.html