本篇用來記錄透過cpp實現在userspace存取Linux上的Device file, 及相關Lib的使用
#include <iostream>
#include <array>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <unistd.h>
int main(){
int file = open("/sys/bus/i2c/devices/6-0054/eeprom", O_RDONLY);
auto result = lseek(file, 0x0000, SEEK_SET);
if (result < 0)
{
std::cout << "fail to seek\n";
return -1;
}
else
{
std::cout << "succeed to seek\n";
}
std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData;
// I2C_SMBUS_BLOCK_MAX from linux/i2c.h
auto data = read(file, blockData.data(), 0x8);
for (size_t i = 0; i < 8; i++)
{
std::cout << unsigned(blockData[i]) << std::endl; //轉成unsigned並顯示
}
return 0;
}
int file = open("/sys/bus/i2c/devices/6-0054/eeprom", O_RDONLY);
透過open回傳File Descriptor給其他需要存取檔案的函式使用,後面加上O_RDONLY表示使用唯讀的方式做開啟,另外還有O_WRONLY、O_RDWR可使用
open 與開啟方式是由fctl.h提供
auto result = lseek(file, 0x0000, SEEK_SET);
透過lseek把讀寫位置從檔案的開始+offset個位置,return 目前的偏移量,SEEK_SET表示從檔案的開始。
lseek 由unistd.h提供
SEEK位置由fcnt.h提供
SEEK_CUR -> 檔案目前往後+offset
SEEK_END -> 檔案結尾往後+offset
std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData;
auto data = read(file, blockData.data(), 0x8);
建立一個uint8_t型態,長度為I2C_SMBUS_BLOCK_MAX
的Array
並使用read讀取0x08個bytes的資料到blockData中
read 由unistd.h 提供
read(int _fd, void _buf, size_t nbytes)
此範例使用stdio.h的fopen、fseek、ftell
int checkEepromSize(std::string path)
{
FILE *pFile;
pFile = fopen("/sys/bus/i2c/devices/6-0054/eeprom", "rd");
auto result = fseek(pFile, 0, SEEK_END);
unsigned long len = (unsigned long)ftell(pFile);
std::cout << "file len = " << len << std::endl;
}
流程:
fopen, fseek, ftell 由stdio.h提供
open 與 fopen有何差異?
- open 是較低階的IO,UNIX的system call,return file descriptor
- fopen 是標準C定義的函數,底層實作也是會call到open,return 一個指向檔案的ptr
- open無緩衝,fopen有緩衝(buffer);在使用read時只分配2K buffer若檔案超過,則須執行多次system call讀取資料,fread可以直接指定buffer大小只需要執行一次從HD讀出
- 由於open是較低級別的IO,可更接近系統可以存取到fopen無法訪問的訊息
- open可指定開啟的權限