如何快速变成平胸:《linux 环境下C编程指南》 小结 ——看下一遍时再修改

来源:百度文库 编辑:偶看新闻 时间:2024/04/28 00:11:05

       《Linux环境下C编程指南》知识总结

一:C语言基础

1.      数据类型

2.      运算符表达式

3.      C程序语句

4.      函数

5.      编译预处理

 

二:vi与emacs

2.1 vi启动退出

2.2 命令行操作

   $ 将光标移动到该行最后

   G 移动到最后一行开头

   nG 将光标移动到n行行首

   Z+Z  表示保存并退出vim

   % 符号匹配功能 “%a”将匹配到 相应的“a”

   .  重复执行上一命令

   u 表示复原功能

   y+y  将光标目前所在位置整行复制

   n+y+y  若按下3yy 则将光标所在行与下面两行一起复制

   p 将复制的内容整行粘贴在光标所在位置

   d+左方向键  将光标前一个字符删除

   d+右    将光标当前字符删除

   d+上     上一行全部删除

   d+ 下    下一行全部删除

   d+d  删除当前行

   n+d+d 向下删除n行

   n+d+下  向下删除n行

   n+d+上  向上删除n行

2.3 命令行模式与输入模式切换

2.4 最后行操作

   :set nu  设置行号

   :/  查找字符串,“/字符串”将高亮显示字符串,n向下找一个,N向上找一个,由上向下。

   :? “?字符串”由下向上查找字符串,

 

三:gcc

Gcc 选项,警告,优化,调试标记,高级选项

从功能上分,预处理、编译、汇编是三个不同的阶段,但GCC的实际操作上,它可以把这三个步骤合并为一个步骤来执行。

gcc test.c这样将编译出一个名为a.out的程序
gcc test.c -o test这样将编译出一个名为test的程序,-o参数用来指定生成程序的名字

 

编译:

第一步、是进行预编译,使用-E参数可以让GCC在预处理结束后停止编译过程:

gcc -E hello.c -o hello.i

预处理的宏定义插入到hello.i中

第二步、是将hello.i编译为目标代码,这可以通过使用-c参数来完成:

gcc -c hello.i -o hello.o

也可以通过源文件直接生成

gcc -c hello.c

第三步、是将生成的目标文件链接成可执行文件:

gcc hello.o -o hello

也可以通过源文件直接生成

gcc -o hello hello.c

,因为警告:

1、-pedantic 选项,那么使用了扩展语法的地方将产生相应的警告信息

2、-Wall 使用它能够使GCC产生尽可能多的警告信息

3、-Werror,它要求GCC将所有的警告当成错误进行处理

库依赖:

1、Linux下的大多数函数都默认:

头文件放到/usr/include/目录下

而库文件则放到/usr/lib/目录下

2、GCC在编译时必须有自己的办法来查找所需要的头文件和库文件。

-I选项可以向GCC的头文件搜索路径中添加新的目录。

例如,如果在/home/xiaowp/include/目录下有编译时所需要的头文件,为了让GCC能够顺利地找到它们,就可以使用-I选项:

gcc -o test test.c -I /home/xiaowp/include

-L选项向GCC的库文件搜索路径中添加新的目录

例如,如果在/home/xiaowp/lib/目录下有链接时所需要的库文件libfoo.so,为了让GCC能够顺利地找到它,可以使用下面的命令

gcc -o test test.c -L /home/xiaowp/lib -lfoo

值得好好解释一下的是-l选项,它指示GCC去连接库文件libfoo.so。

Linux下的库文件在命名时有一个约定,那就是应该以lib三个字母开头,由于所有的库文件都遵循了同样的规范,因此在用-l选项指定链接的库文件名时可以省去lib三个字母,也就是说GCC在对-lfoo进行处理时,会自动去链接名为libfoo.so的文件。

-static选项,强制使用静态链接库

如果在/home/xiaowp/lib/目录下有链接时所需要的库文件libfoo.so和libfoo.a

为了让GCC在链接时只用到静态链接库,可以使用下面的命令:

gcc -o test test.c -L /home/xiaowp/lib -static -lfoo

选项-O可以告诉GCC同时减小代码的长度和执行时间,其效果等价于-O1。

在这一级别上能够进行的优化类型虽然取决于目标处理器,但一般都会包括线程跳转(Thread Jump)和延迟退栈(Deferred Stack Pops)两种优化。

选项-O2告诉GCC除了完成所有-O1级别的优化之外,同时还要进行一些额外的调整工作,如处理器指令调度等。

选项-O3则除了完成所有-O2级别的优化之外,还包括循环展开和其它一些与处理器特性相关的优化工作。

通常来说,数字越大优化的等级越高,同时也就意味着程序的运行速度越快。

许多Linux程序员都喜欢使用-O2选项,因为它在优化长度、编译时间和代码大小之间,取得了一个比较理想的平衡点。

time ./test 查看程序执行时间

优化虽然能够给程序带来更好的执行性能,但在如下一些场合中应该避免优化代码:

程序开发的时候优化等级越高,消耗在编译上的时间就越长,因此在开发的时候最好不要使用优化选项,只有到软件发行或开发结束的时候,才考虑对最终生成的代码进行优化。

资源受限的时候一些优化选项会增加可执行代码的体积,如果程序在运行时能够申请到的内存资源非常紧张(如一些实时嵌入式设备),那就不要对代码进行优化,因为由这带来的负面影响可能会产生非常严重的后果。

跟踪调试的时候在对代码进行优化的时候,某些代码可能会被删除或改写,或者为了取得更佳的性能而进行重组,从而使跟踪和调试变得异常困难。

加速:

使用管道代替编译中临时文件,

-pipe 加速编译

gcc -pipe foo.c -o foo

GCC常用选项

-c 通知GCC取消链接步骤,即编译源码并在最后生成目标文件;

-Dmacro 定义指定的宏,使它能够通过源码中的#ifdef进行检验;

-E 不经过编译预处理程序的输出而输送至标准输出;

-g3 获得有关调试程序的详细信息,它不能与-o选项联合使用;

-Idirectory 在包含文件搜索路径的起点处添加指定目录;

-llibrary 提示链接程序在创建最终可执行文件时包含指定的库;

-O、-O2、-O3 将优化状态打开,该选项不能与-g选项联合使用;

-S 要求编译程序生成来自源代码的汇编程序输出;

-v 启动所有警报;

-Wall 在发生警报时取消编译操作,即将警报看作是错误;

-Werror 在发生警报时取消编译操作,即把报警当作是错误;

-w 禁止所有的报警。

基本上用不到;若非要生成这种文件 不可,可以利用下面的示例命令:行功能上分,预处理、编译、汇编是三个不同的阶段,但GCC的实际操作上,它可以把这三个步骤合并为一个步骤来执行

四:dgb

调试步骤,显示数据,使用断点,使用观察窗口,查看栈信息,查看源信息,查看运行时数据,改变程序执行,core dump 分析

 

五:使用make

1.      make 书写规范

2.      使用命令

3.      使用变量

4.      使用条件判断

5.      使用函数

6.      make运行

7.      隐含规则

8.      make给新函数库文件

9.      高级使用

10.  库使用

 

六:进程控制

1.      进程基本概念

2.      进程相关函数

3.      多个进程间的关系

4.      线程

 

pid_t getpid(void);

pid_t getppid(void);

pid_t getuid(void);

pid_t geteuid(void);

pid_t getgid(void);

pid_t getegid(void);

上面这些函数分别用于获得当前进程的:进程ID、父进程ID、实际用户ID、有效用户ID、实际组ID和有效组ID。

创建子进程

相关函数

pid_t fork(void);

pid_t vfork(void);

说明

除了init等系统进程以外,创建进程的唯一方法就是调用fork函数。调用fork后,子进程完全复制父进程。对子进程,fork返回0;对父进程,fork返回子进程的pid。vfork并不复制父进程的进程空间,在子进程调用exec或者exit之前,子进程在父进程的进程空间运行。

文件共享

子进程继承了父进程打开的文件描述符及其文件位移量,所以可能产生冲突,需要进行同步,也可以父进程等待子进程完成或者父、子进程执行不同的程序段以避免冲突。

fork的用法

父进程希望复制自己,使父、子进程执行不同的代码段。

一个进程要调用一个不同的程序。

 等待进程终止

相关函数

pid_t wait(int *status);

pid_t waitpid(pid_t pid, int *status,int options);

说明

status返回所等待进程的返回状态,可以用一系列的宏来检查这个状态。

调用这两个函数后,当前进程可能会:

阻塞(如果其所以子进程都还在运行)

带子进程的终止状态立刻返回(如果一个子进程以终止,正在等待父进程存取其终止状态)

出错立刻返回(如果它没有任何子进程)

区别

在一个子进程终止前,wait是其调用者阻塞,而waitpid有一选择项可以是调用者不阻塞。

waitpid并不等待第一个终止的子进程,它有选择项可以控制它所等待的进程。

 执行程序

相关函数

int execve(const  char  *path,  char  *const  argv [], char *const envp[]);

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[]);

区别

以上6个函数中execve时系统调用,其他的则是库函数。

根据函数名中的字符:

p表示该函数取文件名作为参数,并用PATH环境变量寻找可执行文件。没有字符p则表示参数为完全路径名。

l表示该函数取一个参数表,它和字符v互斥。v表示该函数取一个参数的数组argv[]。

e表示该函数取envp[]数组作为新程序的环境变量表,没有e则使用当前进程的环境变量表。

 设置用户ID和组ID

相关函数

int setuid(uid_t uid);

int setgid(uid_t gid);

 

int seteuid(uid_t euid);

int setegid(gid_t egid);

 

int setreuid(uid_t ruid, uid_teuid);

int setregid(gid_t rgid, gid_tegid);

规则

关于用setuid函数改变用户ID的规则(也同样适用于setgid函数):

若进程具有root特权,则setuid把RUID、EUID以及SUID都设置为uid。

若进程没有root权限,但uid等于RUID或者SUID,则把EUID设置为uid。

上述条件都不满足,则返回出错,errno设为EPERM。

 执行shell程序

相关函数

int system(const char *cmd);

说明

相当于执行/bin/sh –c cmd.

对于有suid和sgid权限的程序不能使用此函数,会产生安全漏洞。

 用户标识

相关函数

char *getlogin(void);

说明

得到运行该程序的用户的登录名。对于未连接到终端的进程,本函数会失败。

 进程时间

相关函数

clock_t times(struct tms *buf);

说明

用于得到进程自己以及终止子进程的用户CPU时间和系统CPU时间。

 

七:文件操作

1.文件系统简介

2.基于文件描述符的I/O 操作

3.文件其他操作

4.特殊文件操作

八:基于流的输入输出

1. 流简介

2. 基于流的I/O 操作

3. 临时文件

 

linux系统调用与文件I/O操作

linux系统调用

所谓系统调用是指操作系统提供给用户程序的一组“特殊”接口,用户程序可以通过这组“特殊”接口来获得得操作系统内核提供的特殊服务。

在linux中用户程序不能直接访部内核提供的服务。为了更好的保护内核空间,将程序的运行空间分为内核空间和用户空间,他们运行在不同的级上,在逻辑上是相互隔离的。

用户程序接口(API)

在linux中用户编程接口(API)遵循了在UNIX中最流行的应用编程界面标准——POSIX标准。这些系统调用编程接口主要通过C库(libc)实现的。

系统调用、API与系统命令之间的关系见图

文件I/O操作介绍

可用的文件I/O函数——打开文件、读文件、写文件等等。大多数linux文件I/O只需用到5个函数:open、read、write、lseek以及close。不带缓存指的是每read和write都调用内核中的一个系统调用。这些不带缓存的I/O函数不是ANSIC的组成部分,但是POSIX组成部分。

文件描述符

对于内核而言,所有打开文件都由文件描述符引用。文件描述符是一个非负整数。当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。当读、写一个文件时,用open或creat返回的文件描述符标识该文件,将其作为参数传送给read或write。在POSIX.1应用程序中,整数0、1、2应被代换成符号常数STDIN_FILEN0、STDOUT_FILENO和STDERR_FILENO。这些常数都定义在头文件

文件描述符的范围是0~OPEN_MAX。早期的UNIX版本采用的上限值是19(允许每个进程打开20个文件),现在很多系统则将其增加至63。

open函数

#include

#include

#inlcude

int open(const char *pathname,int oflag,.../*,mode_t mode*/);

返回:若成功为文件描述符,若出错为-1

pathname是要打开或创建的文件的名字。

oflag参数可用来说明此函数的多个选择项。

对于open函数而言,仅当创建新文件时才使用第三个参数。

用下列一个或多个常数进行或运算构成oflag参数(这些常数定义在

 

头文件中):

O_RDONLY只读打开。

O_WRONLY只写打开。

O_RDWR读、写打开。

O_APPEND每次写时都加到文件的尾端。

O_CREAT若此文件不存在则创建它。使用此选择项时,需同时说明第三个参数mode,用其说明该新文件的存取许可权位。

O_EXCL如果同时指定了O_CREAT,而文件已经存在,则出错,这可测试一个文件是否存在,如果不存在则创建此文件成为一个原子操作。

O_TRUNC如果此文件存在,而且为只读或只写成功打开,则将其长度截短为0。

O_NOCTTY如果pathname指的是终端设备,则不将此设备分配作为此进程的控制终端。

O_NONBLOCK如果pathname指的是一个FIFO、一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的I/O操作设置非阻塞方式。

O_SYNC使每次write都等到物理I/O操作完成。

 

creat函数

可用creat函数创建一个新文件。

#include

#include

#include

int creat(const char *pathname,mode_t mode);

返回:若成功只为写打开的文件描述符,若出错为-1。注意,此函数等效于:

open (pathname,O_WRONLY |O_CREAT| O_TRUNC,mode);

creat的一个不足之处是它以只写方式打开所创建的文件。

 

close函数

可用close函数关闭一个打开文件:

#include

int close(int filedes);

返回:若成功为0,若出错为-1

当一个进程终止时,它所有的打开文件都由内核自动关闭。很多程序都使用这一功能而不显式地用close关闭打开的文件。

如open.c

#include

#include

#include

#include

#inlcude

#include

 

int main(void){

int fd;

if(fd=open("/tmp/hello.c",O_CREAT|O_TRUNC|O_WRONLY,0600))<0){

perror("open:");

exit(1);

}else

printf("open fiale:hello.c%d/n",fd);

 

if(close(fd)<0){

perror("close:");

exit(1);

}

else

printf("Close hello.c/n");

exit(0);

}

 

lessk函数——文件定位

每个打开文件都有一个与其相关联的“当前文件偏移量”。它是一个非负整数,用以度量从文件开始处计算的字节数。通常,读、写操作都从当前文件偏移理处开始,并使偏移理增加所计或写的字节数。按系统默认,当打开一个文件时,除非指定O_APPEND选择项,否则该偏移量被设置为0。可以调用lseek显式地定位一个打开文件。

#include

#include

off_t lseek(it filesdes,off_t offset,int whence);

返回:若成功为新文件位移,若出错为-1。

对于参数offset的解释与参数whence的值有关。

若whence是SEEK_SET,则将该文件的位移量设置为距文件开始处offset个字节。若whence是SEEK_CUR,则将该文件的位移量设置为其当前值加offset,offset可为正或负。若whence是SEEK_END,则将该文件的位移量设置为文件长度加offset,offset可为正或负。若lseek成功执行,则返回新的文件位移量,为此可以用下列方式确定一个打开文件的当前位移量:

off_t currpos;

currpos=lseek(fd,0,SEEK_CUR);

 

 

read函数

用read函数从打开文件中读数据

#include

ssize_t read(int feledes,void *buff,size_t nbytes);

返回:读到的字节数,若已到文件尾为0,若出错为-1。如read成功,则返回读到的字节数。如已到达文件的尾端,则返回0。有多种情况可使实际读到的字节数小于要求读字节数:

读普通文件时,在读到要求字节数之前已到达了文件尾端。例如,若在到达文件尾端之间还有30个字节,而要求读100个字节,则read返回30,下一次再调用read时,它将返回0(文件尾端)。当从终端设备读时,通常一次最多读一行。

当从网络读时,网络中的缓冲机构可能造成返回值小于所要求读的字节数。某些面向记录的设备,例如磁带,一次最多返回一个记录。读操作从文件的当前位移量处开始,在成功返回之前,该位移量增加实际读得的字节数。

 

 

write函数

用write函数向打开文件写数据。

#include

ssize_t write(int filedes,const void *buff,size_t nbytes);

返回:若成功为已写的字节数,若出错为-1。其返回值通常与参数

 

nbytes的值不同,否则表示出错。write出错的一个常见原因是:磁盘已写满,或者超过了对一个给定进程的文件长度限制。

对于普通文件,写操作从文件的当前位移量处开始。如果在打开该文件时,指定了O_APPEND选择项,则在每次写操作之前,将文件位移量设置在文件的当前结尾处。在一次成功写之后,该文件位移量增加实际写的字节数。见write.c

#include

#include

#include

#include

#include

#include

#include

#define MAXSIZE

int main(void){

int i,fd,size,len;

char *buf="Hello! I'm writing to this file!";

char buf_r[10];

len=strlen(buf);

buf_r[10]='/0';

if((fd=open("/tmp/hello.c",O_CREAT | O_TRUNC | O_RDWR,0666)

 

<0){

perror("open:");

exit(1);

}else

printf("open file hello.c %d/n",fd);

 

if((size=write(fd,buf,len))<0){

perror("write:");

exit(1);

}else

printf("Write %s/n",buf);

 

lseek(fd,0,SEEK_SET);

if((size=read(fd,buf_r,10))<0){

perror("read:");

exit(1);

}else

printf("read form file:%s/n",buf_r);

 

if(close(fd)<0){

perror("close:");

exit(1);

}else

printf("Close hello.c/n");exit(0);

}

 

fcntl函数

fcntl函数可以改变已经打开文件的性质。

#include

#inlcude

#inlcude

int fcntl(int filedes,int cmd,....);

返回:若成功则依赖于cmd,若出错为-1。

fcntl函数有五种功能:

(1)复制一个现存的描述符,新文件描述符作为函数值返回

 

(cmd=F_DUPFD).

(2)获得/设置文件描述符标记,对应于filedes的文件描述符标志作为函数值返回。(cmd=F_GETFD或F_SETFD)。

(3)获得/设置文件状态标志,对应于filedes的文件状态标志作为函数值返回。(cmd=F_GETEL或F_SETFL)。

(4)获得/设置异步I/O有权(cmd=F_GETOWN或F_SETOWN)。

(5)获得/设置记录锁(cmd=F_SETLK,F_SETLKW)。

文件状态的说明见附件。

 

F_SETFL将文件状态设置为第三个参数的值(取为整型值)。可以更改的几个标志是:O_APPEND,O_NONBLOCK,O_SYNC和O_ASYNC.

F_GETOWN取当前接收SIGIO和SIGURG信号的进程ID或进程组ID。

F_SETOWN设置接收SIGIO和SIGURG信号的进程ID或进程组ID。正的arg指定一个进程组ID,负的arg表示等于arg绝对值的一个进程组ID。

 

用fcntl给文件加锁

当多个用户共同使用、操作一个文件的时候,linux通常采用的方未能是给文件上锁,来避免共享资源产生竞争的状态。

文件锁包括建议锁和强制性锁。建议性锁要求上锁文件的进程都要检测是否有锁存在,并尊重已有的锁。强制性锁由内核和系统执行的锁。Fcntl不仅可以实施建议性锁而且还可以实施强制性锁。

 

fcntl函数格式

#include

#include

#include

int fcntl(int filedes,int cmd,... struct flock flockptr);

struct flock 结构

struct flock{

short l_type;   /*F_RDLCK,F_WRLCK, F_UNCLK */

off_t l_start;   /*offset in bytes,relative to l_whence */

short l_whence;  /*SEEK_SET,SEEK_CUR,SEEK_END */

off_t len;    /*length,in bytes */

pid_t l_pid;  /* returned with F_GETLK */

};

 

flock结构说明:所希望的锁类型:F_FDLCK(共享读锁)、F_WRLCK(独占性写锁)或F_UNLCK(解锁一个区域)。要加锁或解锁的区域的起始地址,由l_start和l_whence两者决定。l_start是相对位移量(字节),l_whence则决定了相对位移量的起点。区域的长度,早l_len表示。

关于加锁和解锁区域的说明还要注意下列几点:

(1)该区域可以在当前文件尾端处开始或越过其尾端处开始,但是不能在文件起始位置之前开始或越过该起始位置。

(2)如若l_len为0 ,则表示锁的区域从其起点(由l_start和

 

l_whence决定)开始直至最大可能位置为止。也就是不管添写到该文件中多少数据,它都处于锁的范围。

(3)为了锁整个文件,通常的方法是将l_start说明为0,l_whence说明为SEEK_SET,l_len说明为0。

 

ioctl函数  还得查其它资料

ioctl函数是I/O操作的杂物箱。不能用本章中其他函数表示的I/O操作通常都能用ioctl表示。终端I/O是ioctl的最大使用方面,主要用于设备的I/O控制。

#include /*SVR4*/

#include /*4.3 +BSD * /

int ioctl(int filedes,int request,....);

返回:若出错则为-1,若成功则为其他值。

 

selelct实现I/O复用

I/O处理的五种模型

(1)阻塞I/O模型:若所调用的I/O函数没有完成相关的功能就会使进程挂起,直到相关数据到达才会返回。如:终端、网络设备的访问。

(2)非阻塞模型:当请求的I/O操作不能完成时,则不让进程休眠,而且返回一个错误。如:open,read,write访问。

(3)I/O多路转接型:如果请求的I/O操作阻塞,且他不是真正阴塞I/O,而且让其中的一个函数等待,在这期间,I/O还能进行其他操作。如:select函数。

(4)信号驱动I/O模型:在这种模型下,通过安装一个信号处理程序,系统可以自动捕获特定信号的到来,从而启动I/O。

(5)异步I/O模型:在这种模型下,当一个描述符已准备好,可以启动I/O时,进程会通知内核。由内核进行后续处理,这种用法现在较少。   

关心第一种、第三种和第四种模型,用的比较多。

传向select的参数告诉内核:

(1)我们所关心的描述符。

(2)对于每个描述符我们所关心的条件(是否读一个给定的描述符?是否想烈军属一个给定的描述符?是否关心一个描述符的异常条件?)。

(3)希望等待多长时间(可以永远等待,等待一个固定量时间,或完全不等待)。

从select返回时,内核告诉我们:

(1)已准备好的描述符的数量。

(2)哪一个描述符已准备好读、写或异常条件。

#include/*fd_set daya type*/

#include/*struct timeval*/

#inlcude/*function prototype might be here*/

int select(int numfds,fd_set *readfds,fd_set *writefds,fd_set

 

*execptfds,struct timeval *timeout);

返回:准备就绪的描述符数,若超时则为0,若出错则为-1。

timeout值:

NULL:永远等待,直到捕捉到信号或文件描述符已准备好为止;

具体值:struct timeval类型的指针,若等待为timeout时间还没有文件描述符准备好,就立即返回;

0:从不等待,测试所有指定的描述符并立即返回;

先说明最后一个参数,它指定愿意等待的时间。

struct timeval{

long tv_sec; /*seconds*/

long tv_usec; /*and microseconds*/毫秒

};

select函数根据希望进行的文件操作对文件描述符进行分类处理,这里,对文件描述符的处理主要设计4个宏函数:

FD_AERO(fd_set *set)清除一个文件描述符集;

FD_SET(int fd, fd_set *set)将一个文件描述符加入文件描述符集中。

FD_CLR(int fd,fd_set *set)将一个文件描述符从文件描述符集中清除。

FD_ISSET(int fd,fd_set *set)测试该集中的一个给定位是否有变化;

在使用select函数之间,首先使用FD_ZERO和FD_SET来初始化文件描述符集,并使用select函数时,可循环使用FD_ISSET测试描述符集,在执行完成对相关的文件描述符后,使用FD_CLR来清除描述符集。例子见select.c

#include

#include

#include

#include

#include

int main(void){

int fds[2];

char buf[7];

int i,rc,maxfd;

fd_set inset1,inset2;

struct timeval tv;

if((fds[0]=open("hello1",O_RDWR| O_CREAT,0666))<0)

perror("open hello1");

if((fds[1]=open("hello2",O_RDWR|O_CREAT,0666))<0)

perror("open hello2");

if((rc=write(fds[0],"Hello!/n",7))

printf("rc=%d/n",rc);

 

lseek(fds[0],0,SEEK_SET);

maxfd=fds[0]>fds[1]?fds[0]:fds[1];

FD_ZERO(&inset1);

FD_SET(fds[0],&inset1);

FD_ZERO(&inset2);

FD_SET(fds[1],&inset2);;

tv.tv_sec=2;

tv.tv_usec=0;

while(FD_ISSET(fds[0],&inset1)||FD_ISSET(fds[1],&inset2)){

if(select(maxfd+1,&inset1,&inset2,NULL,&tv)<0)

perror("select");

else{

if(FD_ISSET(fds[0],&inset1)){

rc=read(fds[0],buf,7);

if(rc>0){

buf[rc]='/0';

printf("read:%s/n",buf);

}else

perror("read");

}

if(FD_ISSET(fds[1],&inset2)){

rc=write(fds[1],buf,7);

if(rc>0){

buf[rc]='/0';

printf("rc=%d,write:%s/n",rc,buf);

}else

perror("write");

sleep(10);

}

}

}

exit(0);

}

读取hello1文件的内容,写入到hello2文件中去。

 

 

系统I/O 来自CSDN博客:http://blog.csdn.net/xp55699312/archive/农历二〇〇九年三月初十/4050285.aspx

 

九:内存管理

1.      静态内存与动态内存

2.      安全性问题

3.      内存管理操作

4.      使用链表

5.      内存映射I/O

 

十:信号及信号处理

1.      信号及其使用简介

2.      信号操作的相关系统调用

3.      信号处理潜在危险

 

十一:进程间通信

1.      简介

一般包括:内存共享,信号量,管道,命名管道,消息队列,套接口,全双工管道

2.      共享内存和信号量

什么是sysv?

Shmid_da 结构如何定义?

共享内存的创建与打开

int shmget (key_t,int size,int flag);

附加函数

Void *shmat (int shmid,void *addr,int flag);

分离

Int shmdt (void *addr);

   控制共享内存

   Int shmctl (int shmid,int cmd,shmid_ds *buf);

   信号量数据结构

   Semid_ds

   信号量的创建与打开

   Int semget (key_t key,int nsems,int flag);

   操作

   Int semop (int semid,sttruct sembuf semoparray[],size_t nops);

   控制

   Int semctl (int semid,int semnum,int cmd,union semun arg);-

  

3.      管道通信

管道的创建

   Int pipe (int filedescriptos[2]);

4.      命名管道

5.      消息队列

 

十二:网路编程  十三:底层终端编程