,所以 f d o p e n为写打开并不截断该文件。(例如,若该描述符原来是由 o p e n函数打开的,该文件那时已经存在,则其O _ T R U N C标志将决定是否截短该文件。f d o p e n函数不能截短它为写而打开的任一文件。 )另外,标准I / O添加方式也不能用于创建该文件(因为如若一个描述符引用一个文件,则该文件一定已经存在)。
下面贴一下自己联系函数用的代码,第一个是模仿linux ls -l 功能的函数:
//File Name: myls.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
void mode_to_str(mode_t md,char *str); void format(char *time); int main(int argc,char *argv[]) { char *time; char str_mode[11]; DIR *Pdir; struct stat mystat; struct dirent *myent; if(argc==1) { Pdir=opendir("."); } else { Pdir=opendir(argv[1]); } if(Pdir==NULL) { perror("open fail:"); exit(-1); } printf("no,mode,uid,gid,"); while((myent = readdir(Pdir))!=NULL) { memset(&mystat,0,sizeof(mystat)); stat(myent->d_name,&mystat); memset(str_mode,0,11); mode_to_str(mystat.st_mode,str_mode); time=ctime(&mystat.st_atime); time=format(time); // printf("%s\t",myent->d_name); //printf("size=%d,type=%c,name=%s\n",myent->d_reclen,myent->d_type,myent->d_name); printf("%10s. %2d %8d %8d %5d %s %s\n",str_mode,mystat.st_nlink,getpwuid(mystat.st_uid)->pw_name,getgrgid(mystat.st_gid)->gr_name,mystat.st_size,time,myent->d_name); } return 0; } void mode_to_str(mode_t md,char *str) { strcpy(str,"----------"); if(S_ISDIR(md)) { str[0]='d'; } if(md & S_IRUSR) { str[1]='r'; } if(md & S_IWUSR) { str[2]='w'; } if(md & S_IXUSR) { str[3]='x'; } if(md & S_IRGRP) { str[4]='r'; } if(md & S_IWGRP) { str[5]='w'; } if(md & S_IXGRP) { str[6]='x'; } if(md & S_IROTH) { str[7]='r'; } if(md & S_IWOTH) { str[8]='w'; } if(md & S_IXOTH) { str[9]='x'; } } char *format(char *time) { char *p; while((*time)!=' ') { time++; } p=time; while((*p)!=':') { p++; } p=p+3; (*p)='\0'; return time; }
像文件操作有标准io流一样,管道也支持文件流模式。用来创建连接到另一进程的管道,是通过函数popen和pclose。
函数原型:
#include
FILE* popen(const char* command, const char* open_mode);
int pclose(FILE* fp);
函数popen():允许一个程序将另一个程序作为新进程来启动,并可以传递数据给它或者通过它接收数据。command字符串是要运行的程序名。open_mode必须是“r”或“w”。如果open_mode是“r”,被调用程序的输出就可以被调用程序使用,调用程序利用popen函数返回的FILE*文件流指针,就可以通过常用的stdio库函数(如fread)来读取被调用程序的输出;如果open_mode是“w”,调用程序就可以用fwrite向被调用程序发送数据,而被调用程序可以在自己的标准输入上读取这些数据。
函数pclose():用popen启动的进程结束时,我们可以用pclose函数关闭与之关联的文件流。
Example1:从标准管道流中读取 打印/etc/profile的内容
#include
int main()
{
FILE* fp = popen("cat /etc/profile", "r");
char buf[512] = {0};
while(fgets(buf, sizeof(buf), fp))
{
puts(buf);
}
pclose(fp);
return 0;
}
Example2:写到标准管道流 统计buf单词数
#include
int main()
{
char buf[]={"aaa bbb ccc ddd eee fff ggg hhh"};
FILE *fp = popen("wc -w", "w");
fwrite(buf, sizeof(buf), 1, fp);
pclose(fp);
return 0;
}
管道函数原型:
#include
int pipe(int fds[2]);
管道在程序中用一对文件描述符表示,其中一个文件描述符有可读属性,一个有可写的属性。fds[0]是读,fds[1]是写。
函数pipe用于创建一个无名管道,如果成功,fds[0]存放可读的文件描述符,fds[1]存放可写文件描述符,并且函数返回0,否则返回-1。
通过调用pipe获取这对打开的文件描述符后,一个进程就可以从fds[0]中读数据,而另一个进程就可以往fds[1]中写数据。当然两进程间必须有继承关系,才能继承这对打开的文件描述符。
管道不象真正的物理文件,不是持久的,即两进程终止后,管道也自动消失了。
示例:创建父子进程,创建无名管道,父写子读
#include
#include
#include
int main() { int fds[2] = {0}; pipe(fds); char szBuf[32] = {'\0'}; if(fork() == 0){ //表示子进程 close(fds[1]); //子进程关闭写 sleep(2); //确保父进程有时间关闭读,并且往管道中写内容 if(read(fds[0], szBuf, sizeof(szBuf)) > 0) puts(buf); close(fds[0]); //子关闭读 exit(0); }else{ //表示父进程 close(fds[0]); //父关闭读 write(fds[1], "hello", 6); waitpid(-1, NULL, 0); //等子关闭读 //wr