嵌入式Linux——文件IO编程

Linux系统调用、用户编程接口(API)、系统命令

系统调用

含义:系统调用是操作系统就必须利用系统提供给用户的“特殊接口”,并不直接与程序员进行交互,进行系统调用时,程序运行空间需要从用户空间进入内核空间,处理完后再返回用户空间

分类:系统调用大致可分为进程控制、进程间通信、文件系统控制、系统控制、存储管理、网络管理、socket 控制、用户管理等几类

用户编程接口(API)

含义:实际使用中程序员调用的通常是API

遵循标准:API遵循在 UNIX 中最流行的应用编程界面标准——POSIX 标准(该标准保证应用程序可以在源代码一级上在多种操作系统上移植运行)

系统命令

系统命令相对 API 更高了一层,它实际上是一个可执行程序,它的内部引用了用户编程接口(API)来实现相应的功能。

系统调用与API的关系

API 函数会需要几个系统调用来共同完成函数的功能,甚至还有一些 API 函数不需要调用相应的系统调用(因此它所完成的不是内核提供的服务)

Linux文件及文件描述符概述

Linux 文件分为四类:

  • 普通文件
  • 目录文件
  • 链接文件
  • 设备文件

程序启动时通常会打开的三个文件:

  • 标准输入:文件描述符为0(STDIN_FILENO)
  • 标准输出:文件描述符为1(STDOUT_FILENO)
  • 标准出错处理:文件描述符为2(STDERR_FILENO)

底层文件IO基本操作

#include <sys/types.h> /* 提供类型 pid_t 的定义 */
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int open(const char *pathname, int flags, int perms)
int close(int fd)
ssize_t read(int fd, void *buf, size_t count)
ssize_t write(int fd, void *buf, size_t count)
off_t lseek(int fd, off_t offset, int whence)

文件锁

当有多个用户共同使用、操作一个文件的情况,Linux 通常采用的方法是给文件上锁,来避免共享的资源产生竞争的状态

文件锁分类

建议性锁:由lockf()实现,要求每个上锁文件的进程都,要检查是否有锁存在,并且尊重已有的锁

强制性锁:由fcntl()实现,强制性锁是由内核执行的锁,当一个文件被上锁进行写入操作的时候,内核将阻止其他任何文件对其进行读写操作。采用强制性锁对性能的影响很大,每次读写操作都必须检查是否有锁存在

#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);//lock可传入可传出,由cmd决定 

lockf结构体:

struct flock
{
    short l_type;
    off_t l_start;
    short l_whence;
    off_t l_len;
    pid_t l_pid;
}
/* lock_set.c */
int lock_set(int fd, int type)
{
	struct flock old_lock, lock;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;
	lock.l_type = type;
	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);
		}
	}
	/* l_type 可能已被 F_GETLK 修改过 */
	lock.l_type = type;
	/* 根据不同的 type 值进行阻塞式上锁或解锁 */
	if ((fcntl(fd, F_SETLKW, &lock)) < 0)
	{
		printf("Lock failed:type = %d\n", lock.l_type);
		return 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("Release lock by %d\n", getpid());
		return 1;
	}
	break;
	default:
		break;
	}/* end of switch */
	return 0;
}

发表评论

您的电子邮箱地址不会被公开。