unix高级环境编程 例子 代码实现练习 第十四章:高级IO

来源:互联网 发布:一般淘宝客服打字 编辑:程序博客网 时间:2024/05/23 01:15

程序清单 14-1 长的非堵塞write

/** * 程序清单 14-1 长的非堵塞write P357 * * zy: * 可以运行,和书上类似。 */#include "apue.h"#include "error.c"#include <fcntl.h>#include <errno.h>//定义了通过错误码来回报错误资讯的宏//宏定义为一个int型态的左值, 包含任何函式使用errno功能所产生的上一个错误码#include <fcntl.h>//file controlchar buf[500000];void set_fl(int fd,int flags){//flags就是要准备打开的标志    int val;    if((val= fcntl(fd,F_GETFL,0))<0){        err_sys("fcntl F_GETFL error");    }    val |=flags; //与标志表示打开一个    if(fcntl(fd,F_SETFL,val)<0){        err_sys("fcntl F_SETFL error");    }}void clr_fl(int fd,int flags){//flags就是要关闭的标志    int val;    if((val= fcntl(fd,F_GETFL,0))<0){        err_sys("fcntl F_GETFL error");    }    val &=~flags; //将这个标志关闭    if(fcntl(fd,F_SETFL,val)<0){        err_sys("fcntl F_SETFL error");    }}int main(void){int ntowrite,nwrite;char *ptr;ntowrite=read(STDIN_FILENO,buf,sizeof(buf)); //STDIN_FILENO: Standard file descriptors 文件标识符fprintf(stderr,"read %d bytes\n",ntowrite); //stderr:Standard streams 应该是以流的形式set_fl(STDOUT_FILENO,O_NONBLOCK);ptr=buf;while(ntowrite>0){errno=0;nwrite=write(STDOUT_FILENO,ptr,ntowrite);fprintf(stderr,"nwrite = %d , errno = %d \n",nwrite,errno);if(nwrite>0){ptr+=nwrite;ntowrite-=nwrite;}}clr_fl(STDOUT_FILENO,O_NONBLOCK);exit(0);}

程序清单 14-2  加锁和解锁一个文件区域的函数

/** * 程序清单 14-2  加锁和解锁一个文件区域的函数 * zy: * 有了这几个函数就可以使用下面的宏定义了。#defineread_lock(fd, offset, whence, len) \lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len))#definereadw_lock(fd, offset, whence, len) \lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len))#definewrite_lock(fd, offset, whence, len) \lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len))#definewritew_lock(fd, offset, whence, len) \lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len))#defineun_lock(fd, offset, whence, len) \lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len)) */#include "apue.h"#include "error.c"#include <fcntl.h>int lock_reg(int fd,int cmd, int type,off_t offset,int whence,off_t len){struct flock lock;lock.l_type=type;lock.l_start=offset;lock.l_whence=whence;lock.l_len=len;return (fcntl(fd,cmd,&lock));}

程序清单 14-3 测试一个文件的锁的状态的函数

/** * 程序清单 14-3  测试一个文件的锁的状态的函数 P362 * zy: * 可以使用下面的宏了#defineis_read_lockable(fd, offset, whence, len) \(lock_test((fd), F_RDLCK, (offset), (whence), (len)) == 0)#defineis_write_lockable(fd, offset, whence, len) \(lock_test((fd), F_WRLCK, (offset), (whence), (len)) == 0) */#include "apue.h"#include "error.c"#include <fcntl.h>pid_t lock_test(int fd,int type,off_t offset,int whence,off_t len){struct flock lock;lock.l_type = type;lock.l_start = offset;lock.l_whence=whence;lock.l_len=len;if(fcntl(fd,F_GETLK,&lock)<0){err_sys("fcntl error");}if(lock.l_type==F_ULOCK){//没锁的话return 0;}return (lock.l_pid);//有锁的话返回pid}

程序清单 14-4 死锁检测实例

/** * 程序清单 14-4 死锁检测实例 P362 * zy: * 很神奇 * 我完全没看出这个tell_wait机制有作用,所以我把其注释了 * 注释了之后代码还是正常运行,所以我认为tell_wait在这里是没用的 * 而是系统自己的机制完成了释放另一个进程的拿到的锁的过程asd@asd-desktop:~/workspace/test/src$ ./a.outparent:got the lock, byte 1child:got the lock, byte 0child,writew_lock error: Resource deadlock avoidedparent:got the lock, byte 0asd@asd-desktop:~/workspace/test/src$ * */#include "apue.h"#include "error.c"#include <fcntl.h>#include <fcntl.h>int lock_reg(int fd,int cmd, int type,off_t offset,int whence,off_t len){struct flock lock;lock.l_type=type;lock.l_start=offset;lock.l_whence=whence;lock.l_len=len;return (fcntl(fd,cmd,&lock));}static void lockabyte(const char *name,int fd, off_t offset){if(writew_lock(fd,offset,SEEK_SET,1)<0){err_sys("%s,writew_lock error",name);}printf("%s:got the lock, byte %ld\n",name,offset);}int main(void){int fd;pid_t pid;if((fd=creat("templock",FILE_MODE))<0){err_sys("creat error");}if(write(fd,"ab",2)!=2){err_sys("write error");}//TELL_WAIT();if((pid=fork())<0){err_sys("fork error");}else if(pid==0){lockabyte("child",fd,0);//TELL_PARENT(getppid());//WAIT_PARENT();lockabyte("child",fd,1);}else{lockabyte("parent",fd,1);//TELL_CHILD(pid);//WAIT_CHILD();lockabyte("parent",fd,0);}exit(0);}

程序清单 14-5 在文件的整体上加锁

/** * 程序清单 14-5 在文件的整体上加锁 P365 * zy: * 这里是完成在13-2中的一个函数, * 也就是守护进程对文件加锁 * */#include <unistd.h>#include <fcntl.h>int lockfile(int fd){struct flock fl;fl.l_type=F_WRLCK;fl.l_start=0;fl.l_whence=SEEK_SET;fl.l_len=0;return (fcntl(fd,F_SETLK,&fl));}

程序清单 14-6 确定是否支持强制性锁机制

/** * 程序清单 14-6 确定是否支持强制性锁机制 P369 * zy: * 看样子我的机子是支持强制性锁 * 运行结果:asd@asd-desktop:~/workspace/test/src$ ./a.out temp.lock读锁试图锁上已经被父进程加了写锁的区域得到的错误代码:11read Ok 强制性锁没有其作用,buf=abasd@asd-desktop:~/workspace/test/src$ * */#include "apue.h"#include "error.c"#include <errno.h>#include <fcntl.h>#include <sys/wait.h>void set_fl(int fd,int flags){//flags就是要准备打开的标志    int val;    if((val= fcntl(fd,F_GETFL,0))<0){        err_sys("fcntl F_GETFL error");    }    val |=flags; //与标志表示打开一个    if(fcntl(fd,F_SETFL,val)<0){        err_sys("fcntl F_SETFL error");    }}void clr_fl(int fd,int flags){//flags就是要关闭的标志    int val;    if((val= fcntl(fd,F_GETFL,0))<0){        err_sys("fcntl F_GETFL error");    }    val &=~flags; //将这个标志关闭    if(fcntl(fd,F_SETFL,val)<0){        err_sys("fcntl F_SETFL error");    }}int lock_reg(int fd,int cmd, int type,off_t offset,int whence,off_t len){struct flock lock;lock.l_type=type;lock.l_start=offset;lock.l_whence=whence;lock.l_len=len;return (fcntl(fd,cmd,&lock));}int main(int argc, char **argv) {int fd;pid_t pid;char buf[5];struct stat statbuf;if(argc!=2){fprintf(stderr,"usage:%s filename\n",argv[0]);exit(1);}if((fd=open(argv[1],O_RDWR|O_CREAT|O_TRUNC,FILE_MODE))<0){err_sys("open error");}if(write(fd,"abcdef",6)!=6){err_sys("write error");}/* * 开启强制性锁 */if(fstat(fd,&statbuf)<0){err_sys("fstat error");}if(fchmod(fd,(statbuf.st_mode & ~S_IXGRP)|S_ISGID)<0){err_sys("fchomd error");}//TELL_WAIT();if((pid=fork())<0){err_sys("fork error");}else if( pid>0){if(write_lock(fd,0,SEEK_CUR,0)<0){err_sys("write lock error");}//TELL_CHILD(pid);if(waitpid(pid,NULL,0)<0){err_sys("waitpid error");}}else{//WAIT_PARENT();set_fl(fd,O_NONBLOCK);/** * 我们先上上锁,看看能得到什么 */if(read_lock(fd,0,SEEK_SET,0)!=-1){err_sys("child:read_lock succeeded");}printf("读锁试图锁上已经被父进程加了写锁的区域得到的错误代码:%d\n",errno);/** * 但是我们还是试图去读 */if(lseek(fd,0,SEEK_SET)==-1){err_sys("lseek error");}if(read(fd,buf,2)<0){err_ret("read failed ,因为强制性锁在起作用\n");}else{printf("read Ok 强制性锁没有其作用,buf=%2.2s\n",buf);}}exit(0);}

程序清单 14-7 检查描述符是否引用STREAMS设备

程序清单 14-8 测试isastream函数

/** * 程序清单 14-7 检查描述符是否引用STREAMS设备 P373 * 程序清单 14-8 测试isastream函数 P373 * * zy: * I_CANPPU试图改变属性,如果能改,则是一个stream * * 运行结果:asd@asd-desktop:~/workspace/test/src$ ./a.out /dev/tty /dev/fd /dev/null /etc/motd/dev/tty not a stream: Invalid argument/dev/fd not a stream: Inappropriate ioctl for device/dev/null not a stream: Inappropriate ioctl for device/etc/motd not a stream: Inappropriate ioctl for deviceasd@asd-desktop:~/workspace/test/src$ */#include <stropts.h>//stropts.h - STREAMS interface#include <unistd.h>#include "apue.h"#include <fcntl.h>#include "error.c"int isastream(int fd){return (ioctl(fd,I_CANPUT,0)!=-1);}int main(int argc, char **argv) {int i,fd;for(i=1;i<argc;i++){if((fd=open(argv[i],O_RDONLY))<0){err_ret("%s can't open",argv[i]);continue;}if(isastream(fd)==0){err_ret("%s not a stream",argv[i]);}else{err_msg("%s:stream device",argv[i]);}}}

程序清单 14-9 列表留中的模块名

/** * 程序清单 14-9 列表留中的模块名 P375 * zy: * 运行结果:asd@asd-desktop:~/workspace/test/src$ whoasd      tty7         2014-03-20 09:13asd      pts/0        2014-03-20 10:55 (:0.0)asd@asd-desktop:~/workspace/test/src$ sudo ./a.out /dev/console/dev/console is not a streamasd@asd-desktop:~/workspace/test/src$ sudo ./a.out /dev/pts/0/dev/pts/0 is not a streamasd@asd-desktop:~/workspace/test/src$ * 难道在我的机子上就不是一个STREAM设备? */#include "apue.h"#include <fcntl.h>#include <stropts.h>#include "error.c"int main(int argc, char **argv) {int fd,i,nmods;struct str_list list;if(argc!=2){err_quit("usage:%s <pathname>",argv[0]);}if((fd=open(argv[1],O_RDONLY))<0){err_sys("can't open %s",argv[1]);}if(isastream(fd)==0){err_quit("%s is not a stream",argv[1]);}/* * 看看有多少模块 */if((nmods=ioctl(fd,I_LIST,(void *)0))<0){err_sys("I_LIST error for nmods");}printf("#modelues=%d\n",nmods);/** * 为模块名分配内存 */list.sl_modlist=calloc(nmods,sizeof(struct str_mlist));if(list.sl_modlist==NULL){err_sys("calloc error");}list.sl_nmods=nmods;/** * 拿到所有的名字 */if(ioctl(fd,I_LIST,&list)<0){err_sys("I_LIST error for list");}/** * 打印名字 */for(i=1;i<=nmods;i++){printf("%s : %s\n",(i==nmods)?"driver":"module",list.sl_modlist++->l_name);}}

程序清单 14-10 用getmsg将标准输入复制到标准输出

/** * 程序清单 14-10 用getmsg将标准输入复制到标准输出 P378 * * zy: * linux没有getmsg这个函数。不能运行 * 我自己man了一下没找到。http://bbs.csdn.net/topics/360039652 */#include "apue.h"#include <stropts.h>#include "error.c"#define BUFFSIZE 4096int main(int argc, char **argv) {int n,flag;char ctlbuf[BUFFSIZE],datbuf[BUFFSIZE];struct strbuf ctl,dat;ctl.buf=ctlbuf;ctl.maxlen=BUFFSIZE;dat.buf=datbuf;dat.maxlen=BUFFSIZE;for(;;){flag=0;if((n=getmsg(STDIN_FILENO,&ctl,&dat,&flag))<0){err_sys("getmsg error");}fprintf(stderr,"flag=%d,ctl.len=%d,dat.len=%d\n",flag,ctl.len,dat.len);}  if(dat.len==0){exit(0);} else if(dat.len>0){if(write(STDOUT_FILENO,dat.buf,dat.len)!=dat.len)err_sys("write error");}}

 程序清单 14-11 readn和writen函数

/** * 程序清单 14-11 readn和writen函数 P390 * * zy: * 读写指定量的数据,如果一次没有完成,那么会循环调用while来完成 */#include "apue.h"ssize_t readn(int fd, void *ptr,size_t n){size_t nleft;ssize_t nread;nleft=n;while(nleft>0){if((nread=read(fd,ptr,nleft))<0){if(nleft==n){//这里是出错之后才会执行的语句return(-1);}else{break;}}else if(nread==0){break;}nleft-=nread;ptr +=nread;}return (n-nleft);}ssize_t writen(int fd, void *ptr,size_t n){size_t nleft;ssize_t nwritten;nleft=n;while(nleft>0){if((nwritten=write(fd,ptr,nleft))<0){if(nleft==n){//这里是出错之后才会执行的语句return(-1);}else{break;}}else if(nwritten==0){break;}nleft-=nwritten;ptr +=nwritten;}return (n-nleft);}

程序清单 14-12 readn和writen函数

/** * 程序清单 14-12 用储存映射I/O复制文件 P394 * * zy: * 用共享内存的方式完成了文件的复制 * 运行结果:asd@asd-desktop:~/workspace/test/src$ gcc test2.casd@asd-desktop:~/workspace/test/src$ sudo ./a.out core core2asd@asd-desktop:~/workspace/test/src$ ll core core2-rw-r----- 1 asd asd 4677632 Mar 18 20:06 core-rw-r--r-- 1 asd asd 4677632 Mar 20 12:40 core2asd@asd-desktop:~/workspace/test/src$ */#include "apue.h"#include <fcntl.h>#include <sys/mman.h>#include "error.c"int main(int argc, char **argv) {int fdin,fdout;void *src,*dst;struct stat statbuf;if(argc!=3){err_quit("usage: %s <from file> <to file>",argv[0]);}if((fdin=open(argv[1],O_RDONLY))<0){err_sys("can't open %s for reading",argv[1]);}if((fdout=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,FILE_MODE))<0){err_sys("can't create %s for writing",argv[2]);}if(fstat(fdin,&statbuf)<0){/*为了拿到被复制文件的长度*/err_sys("fstat error");}if(lseek(fdout,statbuf.st_size - 1,SEEK_SET)==-1){err_sys("lseek error");}if(write(fdout,"",1)!=1){err_sys("write error");}if((src=mmap(0,statbuf.st_size,PROT_READ,MAP_SHARED,fdin,0))==MAP_FAILED){err_sys("mmap error for input");}if((dst=mmap(0,statbuf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fdout,0))==MAP_FAILED){err_sys("mmap error for output");}memcpy(dst,src,statbuf.st_size);exit(0);}

0 0
原创粉丝点击