|
|
Home » U++ Library support » U++ Core » LoadFile("/sys/devices/virtual/thermal/ ...") does not work
LoadFile("/sys/devices/virtual/thermal/ ...") does not work [message #58259] |
Wed, 06 April 2022 12:29  |
Tom1
Messages: 1301 Registered: March 2007
|
Ultimate Contributor |
|
|
Hi,
I attempted to read Raspberry Pi 4 SoC temperature with the below code. For some reason using LoadFile does not work:
double GetRaspberryPiTemperature(){
String result = LoadFile("/sys/devices/virtual/thermal/thermal_zone0/temp");
if(!result.IsEmpty()) return 0.001*ScanDouble(~result);
return -55.0;
}
So I had to revert using FILE and fgets instead:
double GetRaspberryPiTemperature(){
FILE *in=fopen("/sys/devices/virtual/thermal/thermal_zone0/temp","rb");
char s[8];
if(fgets(s,8,in)) return 0.001*ScanDouble(s);
return -55.0;
}
Is this expected or is this a bug?
Best regards,
Tom
|
|
|
|
Re: LoadFile("/sys/devices/virtual/thermal/ ...") does not work [message #58292 is a reply to message #58278] |
Tue, 12 April 2022 08:54   |
Tom1
Messages: 1301 Registered: March 2007
|
Ultimate Contributor |
|
|
Hi Mirek,
None of the options below work. The file opens OK, but reading fails with all means:
FileIn in;
in.Open("/sys/devices/virtual/thermal/thermal_zone0/temp");
if(in.IsError()) return -100;
// String result = in.GetLine();
// String result = in.Get(5);
String result = in.GetAll(8);
if(!result.IsEmpty()) return 0.001*ScanInt(~result);
return -55.0;
Best regards,
Tom
|
|
|
|
|
Re: LoadFile("/sys/devices/virtual/thermal/ ...") does not work [message #58299 is a reply to message #58297] |
Wed, 13 April 2022 14:44   |
Tom1
Messages: 1301 Registered: March 2007
|
Ultimate Contributor |
|
|
Hi,
This does work on both Raspberry Pi OS (on RPi4) and Linux Mint (on x86_64):
#include <Core/Core.h>
using namespace Upp;
String LoadFileRaw(const char *filename){
int fd = open(filename,O_RDONLY);
if(fd!=-1){
char buf[4096];
StringBuffer s;
int len;
while((len=read(fd,buf,4096))==4096) s.Cat(buf,len);
if(len>0) s.Cat(buf,len);
close(fd);
if(s.GetCount()>0) return s;
}
return String::GetVoid();
}
CONSOLE_APP_MAIN
{
String meminfo = LoadFileRaw("/proc/meminfo");
Cout() << meminfo << "\n\n";
}
Also:
LoadFileRaw("/sys/devices/virtual/thermal/thermal_zone0/temp");
works fine on RPi4.
Best regards,
Tom
|
|
|
|
Re: LoadFile("/sys/devices/virtual/thermal/ ...") does not work [message #58301 is a reply to message #58300] |
Wed, 13 April 2022 18:45   |
Tom1
Messages: 1301 Registered: March 2007
|
Ultimate Contributor |
|
|
mirek wrote on Wed, 13 April 2022 18:39
I suspect that the problem is somewhere here: Core/BlockStream.cpp:474
Probably that S_IFREG flag test. Maybe using S_IFBLK would fix it?
Mirek
Hi,
Unfortunately this does not help. I think, it opens OK, but fails to read.
Best regards,
Tom
|
|
|
Re: LoadFile("/sys/devices/virtual/thermal/ ...") does not work [message #58302 is a reply to message #58301] |
Wed, 13 April 2022 20:33   |
Tom1
Messages: 1301 Registered: March 2007
|
Ultimate Contributor |
|
|
Hi Mirek,
OK, the problem is here:
bool FileStream::Open(const char *name, dword mode, mode_t tmode) {
Close();
LLOG("Open " << name);
int iomode = mode & ~SHAREMASK;
handle = open(ToSystemCharset(name), iomode == READ ? O_RDONLY :
iomode == CREATE ? O_CREAT|O_RDWR|O_TRUNC :
O_RDWR|O_CREAT,
tmode);
if(handle >= 0) {
struct stat st[1];
fstat(handle, st);
if(!(st->st_mode & S_IFREG) || // not a regular file, e.g. folder - bad things would happen
(mode & NOWRITESHARE) && flock(handle, LOCK_EX|LOCK_NB) < 0) { // lock if not sharing
close(handle);
handle = -1;
return false;
}
int64 fsz = st->st_size;
The 'st->st_size' returned from fstat() above is zero for e.g. "/proc/meminfo". This causes the contents of the file not being read at all. (I tested with a fake length of five bytes and received the five first characters of "/proc/meminfo", so this explains the behavior.)
Best regards,
Tom
More edit: It turns out that files in "/proc" or "/sys" are not really files. Not on disk, but not even in memory. Their contents is generated by the kernel on the fly. So, there is no way to tell their size and so fstat() returns zero. Only way to read them is to just read() them in until EOF.
Maybe they could be read up to the buffer (page) size and if the EOF is encountered, the filesize becomes determined...?
[Updated on: Wed, 13 April 2022 20:46] Report message to a moderator
|
|
|
|
Re: LoadFile("/sys/devices/virtual/thermal/ ...") does not work [message #58404 is a reply to message #58386] |
Wed, 18 May 2022 09:05   |
Tom1
Messages: 1301 Registered: March 2007
|
Ultimate Contributor |
|
|
Hi Mirek,
Well, the LoadFileRaw() implementation above (a couple of messages up) could likely replace LoadFile() on Linux (or POSIX) and Windows does not need any changes. So, I guess it is just Mac that possibly needs attention. (I do not have a Mac, so I cannot really tell.)
EDIT: Or maybe we could use LoadFileRaw() just for files in POSIX that fail to open with LoadFile(). Then allocation of String would be better optimized for normal files.
Best regards,
Tom
[Updated on: Wed, 18 May 2022 09:15] Report message to a moderator
|
|
|
|
|
|
|
|
Re: LoadFile("/sys/devices/virtual/thermal/ ...") does not work [message #58413 is a reply to message #58409] |
Wed, 18 May 2022 10:47   |
Tom1
Messages: 1301 Registered: March 2007
|
Ultimate Contributor |
|
|
mirek wrote on Wed, 18 May 2022 11:29Empty file issue fixed (with len >= 0).
Not sure what do you mean with IsVoid problem, piece of code maybe?
OK, I found the reason causing part of my testing issues:
if(String::GetVoid().IsVoid()) Cout() << "String::GetVoid().IsVoid() works!\n";
else Cout() << "String::GetVoid().IsVoid() fails!\n";
if(IsVoid(String::GetVoid())) Cout() << "IsVoid(String::GetVoid()) works!\n";
else Cout() << "IsVoid(String::GetVoid()) fails!\n";
Best regards,
Tom
EDIT: Improved test code.
[Updated on: Wed, 18 May 2022 10:54] Report message to a moderator
|
|
|
|
|
|
Goto Forum:
Current Time: Sat Apr 26 20:24:45 CEST 2025
Total time taken to generate the page: 0.03073 seconds
|
|
|