湖南网站推广电话,大同哪有做网站的,网站没有备案可以做seo优化吗,招聘网站建设维护目录
dup和dup2函数
fcntl函数
示例程序1
示例程序2
ioctl函数 dup和dup2函数
#include unistd.h
int dup(int oldfd);
int dup2(int oldfd, int newfd): dup 函数复制 oldfd 参数所指向的文件描述符。 参数#xff1a; oldfd#xff1a;要复制的文件描述符的…目录
dup和dup2函数
fcntl函数
示例程序1
示例程序2
ioctl函数 dup和dup2函数
#include unistd.h
int dup(int oldfd);
int dup2(int oldfd, int newfd): dup 函数复制 oldfd 参数所指向的文件描述符。 参数 oldfd要复制的文件描述符的整数值。 返回值 返回新的文件描述符如果出错则返回 -1并设置 errno。 新的文件描述符和oldfd共享所有的锁定读写指针和各项权限和标志位如果用lseek对某个文件描述符操作另一个文件描述符的读写指针也会跟着变动 dup2 函数将 newfd 参数指定的文件描述符设置为 oldfd 参数指定的文件描述符的副本。 参数 oldfd要复制的文件描述符的整数值。newfd要设置为副本的新文件描述符的整数值。 返回值 返回新的文件描述符即 newfd如果出错则返回 -1并设置 errno。 示例 #include stdio.h
#include unistd.hint main() {int fd1 open(file.txt, O_RDONLY);int fd2 open(newfile.txt, O_WRONLY | O_CREAT, 0644);dup2(fd1, 10); // 将文件描述符 10 设置为 fd1 的副本dup2(fd2, 11); // 将文件描述符 11 设置为 fd2 的副本// 现在文件描述符 10 与 fd1 指向相同的文件文件描述符 11 与 fd2 指向相同的文件close(fd1);close(fd2);return 0;
} 若newfd已经被程序使用系统会将其关闭以释放该文件描述符若newfdoldfd则不会关闭该文件。
fcntl函数
#include unistd.h
#include fcntl.h
int fentl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
功能根据cmd的值的不同而不同失败一般返回-1 复制文件描述符F_DUPFD int new_fd fcntl(old_fd, F_DUPFD, 0); 这个命令用于复制文件描述符 old_fd并返回一个新的文件描述符 new_fd 在 fcntl 函数的 F_DUPFD 命令中第三个参数常被称为 arg是用于指定新的文件描述符的最小值。这个参数告诉系统在哪里开始搜索未使用的文件描述符来复制。如果指定的值是 0系统会选择一个未使用的最小文件描述符号。如果你希望指定一个特定的文件描述符可以传递你想要的值。 F_GETFD int flags fcntl(fd, F_GETFD); 用于获取文件描述符 fd 的标志例如 close-on-exec 标志。 如果 FD_CLOEXEC 标志被设置说明文件描述符在 exec 被调用时会被关闭。否则说明文件描述符会保持打开状态。 可以这样判断 int flags fcntl(fd, F_GETFD);
if (flags FD_CLOEXEC) {printf(FD_CLOEXEC flag is set.\n);} else {printf(FD_CLOEXEC flag is not set.\n);} F_SETFD fcntl(fd, F_SETFD, FD_CLOEXEC);//比如arg是FD_CLOEXEC 用于设置文件描述符 fd 的标志例如设置 close-on-exec 标志。 F_GETFL int flags fcntl(fd, F_GETFL); 用于获取文件描述符 fd 的文件状态标志如读写模式和非阻塞标志。 F_SETFL fcntl(fd, F_SETFL, O_NONBLOCK); 用于设置文件描述符 fd 的文件状态标志如设置非阻塞标志。 Linux系统只能设置O_APPEND,O_NONBLOCK,O_ASYNC,含义与open函数里的一致 示例程序1
演示fcntl的一些功能
#include cstdio
#includesys/types.h
#includesys/stat.h
#includefcntl.h
#includeunistd.h
#includecerrno
using namespace std;
//自定义错误处理函数
void my_err(const char *err_string,int line){fprintf(stderr,line:%d ,line);perror(err_string);exit(1);
}
int main(){int ret;int access_mode;int fd;if((fdopen(exanple_64,O_CREAT|O_TRUNC|O_RDWR,S_IRWXU))-1)my_err(open,__LINE__);//设置文件打开方式if((retfcntl(fd,F_SETFL,O_APPEND))-1)my_err(fcntl,__LINE__);//获取文件打开方式if((retfcntl(fd,F_GETFL,0))-1)//0可以去掉my_err(fcntl,__LINE__);access_moderetO_ACCMODE;if(access_modeO_RDONLY)printf(example_64 access mode:read only);else if(access_modeO_WRONLY)printf(example_64 access mode:write only);else if(access_modeO_RDWR)printf(example_64 access mode:readwrite);if(retO_APPEND)printf( ,append);if(retO_NONBLOCK)printf(,nonblock);if(retO_SYNC)printf(,sycn);printf(\n);return 0;
}
运行结果是
结果解释虽然open的时候设置的是O_TRUNC是将文件截断为0但是后面的代码用fcntl修改打开方式为O_APPEND所以O_APPEND是存在的。不过效果依然是截断文件会清空。因为open的时候设置的是截断
retO_ACCMODE是取得文件打开方式的掩码它其实就是3 。因为文件打开方式有三种是2位的所以需要11(二进制)也就是3 。
if(ret O_APPEND) 这句代码用于检查文件状态标志中是否设置了 O_APPEND 标志。 接下来的fcntl函数3种功能都和文件记录锁有关因此先介绍一下文件记录锁。 当有多个进程同时对某一文件进行操作时,就有可能发生数据的不同步从而引起错误该文件的最后状态取决于写该文件的最后一个程序。但是对于有些应用程序如数据库有时进程需要确保它正在单独写一个文件。为了向进程提供这种功能Linux系统提供了记录锁机制。 Linux 的文件记录锁能提供非常详细的控制它能对文件的某一区域进行文件记录锁的控制。当fentl用于管理文件记录锁的操作时第三个参数指向一个struct flock *lock的结构:
struct flock {short l_type; /* 锁的类型: F_RDLCK共享读锁、F_WRLCK独占写锁、F_UNLCK释放锁 */short l_whence; /* l_start 的解释方式: SEEK_SET相对于文件的起始位置、SEEK_CUR相对于当前文件位置、SEEK_END相对于文件的末尾 */off_t l_start; /* 锁的起始位置即锁定范围的起始偏移量 */off_t l_len; /* 锁定的字节数即锁定范围的长度 */pid_t l_pid; /* 执行 F_GETLK 命令时包含持有锁的进程的进程ID */
};l_type锁的类型可以是以下之一 F_RDLCK共享读锁。F_WRLCK独占写锁。F_UNLCK释放锁。 l_whence指定 l_start 的解释方式可以是以下之一 SEEK_SET相对于文件的起始位置。SEEK_CUR相对于当前文件位置。SEEK_END相对于文件的末尾。 l_start锁的起始位置即锁定范围的起始偏移量。 l_len锁定的字节数即锁定范围的长度。 l_len 字段为0通常表示锁定或解锁整个文件。 l_pid在执行 F_GETLK 命令时将包含持有锁的进程的进程ID。 多个进程在一个给定的字节上可以有一把共享的读锁但是在一个给定字节上的写锁则只能由一个进程单独使用。进一步而言如果在一个给定字节上已经有一把或多把读锁则不能在该字节上再加写锁;如果在一个字节上已经有一把独占性的写锁则不能再对它加任何读锁(锁的不兼容规则)。一个进程只能设置某一文件区域上的一种锁。如果某一文件区域已经存在文件记录锁了则如果此时再设置新的锁在该区域的话旧的锁将会被新的锁取代。
为了锁整个文件通常的方法是将l_start说明为0l_whence说明为SEEK_SET,l_len说明为0。 F_GETLK - 获取文件锁信息 struct flock lock; fcntl(fd, F_GETLK, lock); 此命令用于获取文件描述符 fd 上的锁信息这些信息会被存储在 struct flock 结构体中。通过检查结构体中的字段可以了解关于文件锁的信息例如锁定的类型、锁定范围等。 F_SETLK - 设置文件锁 fcntl(fd, F_SETLK, lock); 此时fcntl系统调用被用来设置或释放锁当l_type取 F_RDLCK 或F_WDLCK时在由l_whence、l_ start和l_len指定的区域上设置锁;当l_type取F_UNLCK时则释放锁。如果锁被其他进程占用则返回-1并设置errno为 EACCES 或EAGAIN。 需要注意的是当设置一个共享锁(读锁)时第一个参数fd所指向的文件必须以可读方式打开;当设置一个互斥锁(写锁)时第一个参数fd所指向的文件必须以可写方式打开;当设置两种锁时第一个参数fd所指向的文件必须以可读可写方式打开。当进程结束或文件描述符fd被close系统调用时,锁会自动释放。 F_SETLKW - 设置文件锁并等待 fcntl(fd, F_SETLKW, lock); 此命令与 F_SETLK 类似但是如果无法获取所请求的锁F_SETLKW 会使调用进程进入阻塞状态直到可以获取锁为止。这可以用于在获取锁之前等待其他进程释放锁。 成功返回0失败返回-1。
示例程序2
#includeiostream
#includecstring
#include cstdio
#includesys/types.h
#includesys/stat.h
#includefcntl.h
#includeunistd.h
#includecerrno
using namespace std;
//自定义错误处理函数
void my_err(const char *err_string,int line){fprintf(stderr,line:%d ,line);perror(err_string);exit(1);
}
int lock_set(int fd,struct flock *lock){if(fcntl(fd,F_SETLK,lock)0){//set success if(lock-l_typeF_RDLCK)printf(set read lock,pid:%d\n,getpid());else if(lock-l_typeF_WRLCK)printf(set write lock,pid:%d\n,getpid());else if(lock-l_typeF_UNLCK)printf(release lock,pid:%d,getpid());}else{//failperror(lock operation fail\n);return -1;}return 0;
}
//test,only success return 0
int lock_test(int fd,struct flock *lock){if(fcntl(fd,F_GETLK,lock)0){//successif(lock-l_typeF_UNLCK){//释放可行printf(lock can be set in fd);return 0;}else{//已经有其他锁了则失败if(lock-l_typeF_RDLCK)printf(cant set lock,read lock has been set by:%d\n,lock-l_pid);else if(lock-l_typeF_WRLCK)printf(cant be set lock,write lock has been set by:%d\n,lock-l_pid);return -2;}}else{perror(get incompatible locks fail);return -1;}
}
int main(){int fd;int ret;struct flock lock;char read_buf[32];if((fdopen(example_65,O_CREAT|O_TRUNC|O_RDWR,S_IRWXU))-1)my_err(open,__LINE__);if(write(fd,test lock,10)!10)my_err(write,__LINE__);//init lockmemset(lock,0,sizeof(struct flock));lock.l_start 0;lock.l_whence SEEK_SET;lock.l_len0;//set read locklock.l_typeF_RDLCK;if(lock_test(fd,lock)0){//test succeededlock.l_start0;lock.l_whenceSEEK_SET;lock.l_len0;lock.l_typeF_RDLCK;lock_set(fd,lock);}//read datalseek(fd,0,SEEK_SET);if((retread(fd,read_buf,10))-1)my_err(read,__LINE__);read_buf[ret]\0;printf(%s\n,read_buf);getchar();//set write locklock.l_typeF_WRLCK;if(lock_test(fd,lock)0){lock.l_start0;lock.l_whenceSEEK_SET;lock.l_len0;lock.l_typeF_WRLCK;lock_set(fd,lock);}//releaselock.l_typeF_UNLCK;lock_set(fd,lock);close(fd);return 0;
}
运行结果
结果解释首先测试能不能在文件上加读锁测试成功所以加了读锁然后读文件内容为test lock。之后测试能不能加写锁发现可以就加了写锁。最后释放锁。
注意这是在同一个进程内的所以先加读锁再加写锁会覆盖写锁。但是如果是不同进程就不可以先加读锁再加写锁。
为了演示锁的不兼容性这次程序在不同终端执行 再在另一个终端执行 可以看到两个读锁都可以设置
这时候在第二个终端任意按一个键按理说接下来要设置写锁但是 失败了因为进程1已经设置了读锁进程2就不能设置写锁了。
现在既然进程2已经释放锁了我们回到进程1按下按键试试 因为进程2的锁已经释放了只有进程1本进程的读锁同一进程可以先读锁后写锁所以成功。 fcntl还有一些功能如下图 ioctl函数
#include sys/ioctl.h
int ioctl (int fd, int request,..)
我暂时也看不懂示例程序所以这个函数就跳过吧