今日命令在vim中使用:vsplit ./include/io.h
是以垂直方式打开io.h文件
同理:split ./include/io.h
是以水平方式打开io.h文件
可以用fcntl 函数改变一个已打开的文件的属性,可以重新设置读、写、追加、非阻塞等标志(这些标志称为File StatusFlag),而不必重新open 文件。
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
这个函数和open 一样,也是用可变参数实现的,可变参数的类型和个数取决于前面的cmd 参数。
针对第2个参数,int cmd fcntl函数有五种功能:
• 复制一个现存的描述符(cmd=F_DUPFD) 。
• 获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD) 。
• 获得/设置文件状态标志(cmd=F_GETFL或F_SETFL) 。
• 获得/设置异步I/O有权(cmd=F_GETOWN或F_SETOWN) 。
• 获得/设置记录锁(cmd=F_GETLK,F_SETLK或F_SETLKW)。
我们将涉及与进程表项中各文件描述符相关联的文件描述符标志, 以及每个文件表项中的文件状态标志,
一~复制文件描述符
• F_DUPFD 复制文件描述符filedes,新文件描述符作为函数值返回。它是尚未打开的各
描述符中大于或等于第三个参数值(取为整型值)中各值的最小值。新描述符与 filedes 共享同
一文件表项。但是,新描述符有它自己的一套文件描述符标志,其 F D _ C L O E X E C
文件描述符标志则被清除。
• F_GETFD 对应于filedes 的文件描述符标志作为函数值返回。当前只定义了一个文件描
述符标志FD_CLOEXEC。
• F_SETFD 对于filedes 设置文件描述符标志。新标志值按第三个参数 (取为整型值)设置。
应当了解很多现存的涉及文件描述符标志的程序并不使用常数 F D _ C L O E X E C,而是将此
标志设置为0(系统默认,在exec时不关闭)或1(在exec时关闭)。
二~文件描述符号,套接口 属性相关
• F_GETFL 对应于filedes 的文件状态标志作为函数值返回。在说明 open函数时,已说明
了文件状态标志 不幸的是,三个存取方式标志 (O_RDONLY,O_WRONLY,以及O_RDWR)并不各占1位。(正
如前述,这三种标志的值各是 0、1和2,由于历史原因。这三种值互斥 — 一个文件只能有这
三种值之一。 )因此首先必须用屏蔽字 O_ACCMODE相与 取得存取方式位,然后将结果与这三种值
相比较。
• F_SETFL 将文件状态标志设置为第三个参数的值 (取为整型值)。 可以更改的几个标志是:
O_APPEND,O_NONBLOCK,O_SYNC和O_ASYNC。
fcntl的文件状态标志共有7个,O_RDONLY,O_WRONLY,O_RDWR,O_APPEND,O_NONBLOCK,O_SYNC和O_ASYNC
三~信号驱动I/O , 带外数据,设置套接口接受信号的属主
SIGIO,跟信号驱动I/O有关
SIGURG, 和接受带外数据有关
• F_GETOWN 取当前接收SIGIO和SIGURG信号的进程ID或进程组ID。12.6.2节将论述这
两种4.3+BSD异步I/O信号。
• F_SETOWN 设置接收SIGIO和SIGURG信号的进程ID或进程组ID。正的arg指定一个进
程ID,负的arg表示等于arg绝对值的一个进程组ID。
struct flock
{
short_l_type; /*锁的类型*/
short_l_whence; /*偏移量的起始位置:SEEK_SET,SEEK_CUR,SEEK_END*/
off_t_l_start; /*加锁的起始偏移*/
off_t_l_len; /*上锁字节*/
pid_t_l_pid; /*锁的属主进程ID */
};
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
pid_t pid;
//以追加的形式打开文件
int fd = fd = open("test.txt", O_TRUNC | O_RDWR | O_APPEND | O_CREAT, 0777);
if(fd < 0)
{
perror("open");
return -1;
}
printf("fd = %d\n", fd);
fcntl(fd, F_SETFD, 0);//关闭fd的close-on-exec标志
write(fd, "hello c program\n", strlen("hello c program!\n"));
pid = fork();
if(pid < 0)
{
perror("fork");
return -1;
}
if(pid == 0)
{
printf("fd = %d\n", fd);
int ret = execl("./main", "./main", (char *)&fd, NULL);
if(ret < 0)
{
perror("execl");
exit(-1);
}
exit(0);
}
wait(NULL);
write(fd, "hello c++ program!\n", strlen("hello c++ program!\n"));
close(fd);
return 0;
}
main函数
int main(int argc, char *argv[])
{
int fd = (int)(*argv[1]);//描述符
printf("fd = %d\n", fd);
int ret = write(fd, "hello linux\n", strlen("hello linux\n"));
if(ret < 0)
{
perror("write");
return -1;
}
close(fd);
return 0;
}
用命令F_GETFL和F_SETFL设置文件标志,比如阻塞与非阻塞
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
/**********************使能非阻塞I/O********************
*int flags;
*if(flags = fcntl(fd, F_GETFL, 0) < 0)
*{
* perror("fcntl");
* return -1;
*}
*flags |= O_NONBLOCK;
*if(fcntl(fd, F_SETFL, flags) < 0)
*{
* perror("fcntl");
* return -1;
*}
*******************************************************/
/**********************关闭非阻塞I/O******************
flags &= ~O_NONBLOCK;
if(fcntl(fd, F_SETFL, flags) < 0)
{
perror("fcntl");
return -1;
}
*******************************************************/
int main()
{
char buf[10] = {0};
int ret;
int flags;
//使用非阻塞io
if(flags = fcntl(STDIN_FILENO, F_GETFL, 0) < 0)
{
perror("fcntl");
return -1;
}
flags |= O_NONBLOCK;
if(fcntl(STDIN_FILENO, F_SETFL, flags) < 0)
{
perror("fcntl");
return -1;
}
while(1)
{
sleep(2);
ret = read(STDIN_FILENO, buf, 9);
if(ret == 0)
{
perror("read--no");
}
else
{
printf("read = %d\n", ret);
}
write(STDOUT_FILENO, buf, 10);
memset(buf, 0, 10);
}
return 0;
}
struct flcok
{
short int l_type; /* 锁定的状态*/
//这三个参数用于分段对文件加锁,若对整个文件加锁,则:l_whence=SEEK_SET,l_start=0,l_len=0;
short int l_whence;/*决定l_start位置*/
off_t l_start; /*锁定区域的开头位置*/
off_t l_len; /*锁定区域的大小*/
pid_t l_pid; /*锁定动作的进程*/
};
l_type 有三种状态:
F_RDLCK 建立一个供读取用的锁定
F_WRLCK 建立一个供写入用的锁定
F_UNLCK 删除之前建立的锁定
l_whence 也有三种方式:
SEEK_SET 以文件开头为锁定的起始位置。
SEEK_CUR 以目前文件读写位置为锁定的起始位置
SEEK_END 以文件结尾为锁定的起始位置。
#include "filelock.h"
/* 设置一把读锁 */
int readLock(int fd, short start, short whence, short len)
{
struct flock lock;
lock.l_type = F_RDLCK;
lock.l_start = start;
lock.l_whence = whence;//SEEK_CUR,SEEK_SET,SEEK_END
lock.l_len = len;
lock.l_pid = getpid();
// 阻塞方式加锁
if(fcntl(fd, F_SETLKW, &lock) == 0)
return 1;
return 0;
}
/* 设置一把读锁 , 不等待 */
int readLocknw(int fd, short start, short whence, short len)
{
struct flock lock;
lock.l_type = F_RDLCK;
lock.l_start = start;
lock.l_whence = whence;//SEEK_CUR,SEEK_SET,SEEK_END
lock.l_len = len;
lock.l_pid = getpid();
// 非阻塞方式加锁
if(fcntl(fd, F_SETLK, &lock) == 0)
return 1;
return 0;
}
/* 设置一把写锁 */
int writeLock(int fd, short start, short whence, short len)
{
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_start = start;
lock.l_whence = whence;
lock.l_len = len;
lock.l_pid = getpid();
//阻塞方式加锁
if(fcntl(fd, F_SETLKW, &lock) == 0)
return 1;
return 0;
}
/* 设置一把写锁 */
int writeLocknw(int fd, short start, short whence, short len)
{
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_start = start;
lock.l_whence = whence;
lock.l_len = len;
lock.l_pid = getpid();
//非阻塞方式加锁
if(fcntl(fd, F_SETLK, &lock) == 0)
return 1;
return 0;
}
/* 解锁 */
int unlock(int fd, short start, short whence, short len)
{
struct flock lock;
lock.l_type = F_UNLCK;
lock.l_start = start;
lock.l_whence = whence;
lock.l_len = len;
lock.l_pid = getpid();
if(fcntl(fd, F_SETLKW, &lock) == 0)
return 1;
return 0;
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("usage: a.out <fd>\n");
exit(1);
}
int val = 0;
if ((val = fcntl(atoi(argv[1]), F_GETFL)) < 0)
{
printf("fcntl error for fd %d\n", atoi(argv[1]));
exit(1);
}
switch(val & O_ACCMODE)
{
case O_RDONLY:
printf("read only");
break;
case O_WRONLY:
printf("write only");
break;
case O_RDWR:
printf("read write");
break;
default:
printf("invalid access mode\n");
exit(1);
}
if (val & O_APPEND)
printf(", append");
if (val & O_NONBLOCK)
printf(", nonblocking");
printf("\n");
return 0;
}
void
set_fl(int fd, int flags) /* flags are file status flags to turn on */
{
int val;
if ( (val = fcntl(fd, F_GETFL, 0)) < 0)
{
printf("fcntl F_GETFL error");
exit(1);
}
val |= flags; /* turn on flags */
//重新设置文件状态标志(val为新文件的文件状态标志)
if (fcntl(fd, F_SETFL, val) < 0)
{
printf("fcntl F_SETFL error");
exit(1);
}
}
void
clr_fl(int fd, int flags)
{
int val;
if ((val = fcntl(fd, F_GETFL, 0)) == -1)
{
syslog(LOG_ERR, __FILE__, __LINE__,"fcntl() error : %s", strerror(errno));
exit(1);
}
val &= ~flags; /* turn flags off */
if (fcntl(fd, F_SETFL, val) == -1)
{
syslog(LOG_ERR, __FILE__, __LINE__,"fcntl() error : %s", strerror(errno));
exit(1);
}
return;
}