您的位置:首页 > 运维架构 > Linux

linux文件读写 文件锁、select、poll

2011-10-08 21:29 274 查看
一、文件锁

文件锁用于多个用户共同使用或操作同一个文件。有读锁的时候可以再加读锁,不能再加写锁。有写锁的时候,不能加任何锁,加读锁时,该描述符必须是读打开,加写锁时,该描述符必须是写打开,且只在进程间有用。



重写的上锁方法

//lock.c
int lock_set(int fd,int type){
    struct flock lock;

    lock.l_type=type;
    lock.l_start=0;
    lock.l_whence=SEEK_SET;
    lock.l_len = 0;
    lock.l_pid=-1;

    fcntl(fd,F_GETLK,&lock);
    if(lock.l_type!=F_UNLCK){
        if(lock.l_type == F_RDLCK)
            printf("Read lock already set by %d!\n",lock.l_pid);
        else if(lock.l_type == F_WRLCK)
            printf("Write lock already set by %d!\n",lock.l_pid);
    }
    lock.l_type = type;
    //此处的F_SETLKW为F_SETLK的阻塞版本,当无法获取锁时进入睡眠等待状态
    if(fcntl(fd,F_SETLKW,&lock)<0){
        printf("Lock failed:type=%d!\n",lock.l_type);
        exit(1);
    }

    switch(lock.l_type){
        case F_RDLCK:
            printf("read lock set by %d\n",getpid());
            break;
        case F_WRLCK:
            printf("write lock set by %d\n",getpid());
            break;
        case F_UNLCK:
            printf("UN lock set by %d\n",getpid());
            break;
        default:
            break;
    }
}


上写锁

#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include"lock.c"

int main(){
    int fd;
    fd=open("readme",O_RDWR|O_CREAT,0666);
    if(fd<0){
        printf("Open file error\n");
        exit(1);
    }
    lock_set(fd,F_WRLCK);
    getchar();
    lock_set(fd,F_UNLCK);
    getchar();
    return 0;

}


上读锁

#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include"lock.c"

int main(){
    int fd;
    fd=open("readme",O_RDWR|O_CREAT,0666);
    if(fd<0){
        printf("Open file error\n");
        exit(1);
    }
    lock_set(fd,F_RDLCK);
    getchar();
    lock_set(fd,F_UNLCK);
    getchar();
    return 0;

}

在两个终端中测试:

两个终端可以同时加上读锁。

有一个终端加上读锁,则必须等读锁释放才能加写锁。

有一个终端加写锁必须释放才能加别的锁。


二、多路复用:select、poll
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<memory.h>
#define MAX(a,b) (a>b?a:b)

int main(){
    int fd[3];
    char buff[1024];
    int res,max_fd,i,num;
    fd_set insert,temp_insert;
    struct timeval tv;
    fd[0]=0;
    if((fd[1]=open("in1",O_RDONLY|O_NONBLOCK))<0){
        printf("open in1 error!\n");
        return 1;
    }
    if((fd[2]=open("in2",O_RDONLY|O_NONBLOCK))<0){
        printf("open in2 error!\n");
        return 1;
    }
    //选出最大的fd,select()函数用的
    max_fd=MAX(MAX(fd[0],fd[1]),fd[2]);
    //清空fd_set
    FD_ZERO(&insert);
    for(i=0;i<3;i++){
        FD_SET(fd[i],&insert);
    }
    //设置延迟
    tv.tv_sec=60;
    tv.tv_usec=0;

    while(FD_ISSET(fd[0],&insert) || FD_ISSET(fd[1],&insert) || FD_ISSET(fd[2],&insert)){
        temp_insert = insert;
        //select函数会对fd_set产生修改,只保存变化的文件符,所以要用一个temp
        res=select(max_fd+1,&temp_insert,NULL,NULL,&tv);
        switch(res){
            case -1:
                    printf("select error!\n");
                    return 1;
                    break;
            case 0:
                    printf("time out\n");
                    return 1;
                    break;
            default:
                    for(i=0;i<3;i++){
                        if(FD_ISSET(fd[i],&temp_insert)){
                                memset(buff,0,1024);
                                num=read(fd[i],buff,1024);
                                if(num<0){
                                    return 1;
                                }else if(num == 0){
                                    close(fd[i]);
                                    FD_CLR(fd[i],&insert);
                                }else{
                                    if(i == 0){
                                        if((buff[0] == 'q') || (buff[0] == 'Q')){
                                            return 0;
                                        }
                                    }
                                    write(STDOUT_FILENO,buff,num);

                                }
                        }
                    }
            }
    }
}




poll用法与select很相似,只是在一些变量上有些不同:



#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>

#define MAX_BUFFER_SIZE 1024
#define IO_IN_FILES 3
#define TIME_DELAY 60000

int main() {
	struct pollfd fds[IO_IN_FILES];
	char buff[MAX_BUFFER_SIZE];
	int i,res,real_read;

	fds[0].fd=0;
	if((fds[1].fd=open("in1",O_RDONLY|O_NONBLOCK))<0) {
		printf("Open in1 error!\n");
		return 1;
	}
	
	if((fds[2].fd=open("in2",O_RDONLY|O_NONBLOCK))<0) {
		printf("Open in2 error!\n");
		return 1;
	}

	for(i=0;i<IO_IN_FILES;i++)
		fds[i].events=POLLIN;
	
	while(fds[0].events||fds[1].events||fds[2].events) {
		res=poll(fds,IO_IN_FILES,TIME_DELAY);

		switch(res) {
			case -1:
				printf("POLL error!\n");
				return 1;
				break;
			case 0:
				printf("Time out!\n");
				return 1;
				break;
			default:
				for(i=0;i<IO_IN_FILES;i++) {
					if(fds[i].revents) {
						memset(buff,0,MAX_BUFFER_SIZE);
						real_read=read(fds[i].fd,buff,MAX_BUFFER_SIZE);
						if(real_read<0){
							printf("Read error!\n");
							return 1;
						} else if (real_read==0) {
							close(fds[i].fd);
							fds[i].events=0;
						} else {
							if (i==0) {
								if((buff[0]=='q')||(buff[0]=='Q'))
									return 0;
							} else {
								write(STDOUT_FILENO, buff,real_read);
							//	buff[real_read]='\0';
							//	printf("%s",buff);
							}
						}
							
					}

				}
		}
	}	
	
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: