Show memory and cpu in C - c

how can I see my CPU mhz and Free mem (like free) in OpenBSD with a C code?

Using BSD sysctl(3) to get the live CPU frequency and posix sysconf(3) for free.
#include <stdio.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <unistd.h>
main (argc, argv)
char **argv;
{
size_t sz;
auto psize, cpuspeed, getMhz[] = {CTL_HW, HW_CPUSPEED};
sz = sizeof(cpuspeed);
sysctl(getMhz, 2, &cpuspeed, &sz, NULL, 0);
printf("CPU: %d MHz Free: %ld MB\n", cpuspeed, (sysconf(_SC_AVPHYS_PAGES)*sysconf(_SC_PAGESIZE))>>20
);
return 0;
}

For free, use the source. CPU clock speed is trickier. dmesg | grep CPU | grep Hz will do it in a shell. You may want to try parsing your system log.

Look at the popen function. It creates a pipe, forks a given shell command, and returns a file descriptor you can read from.
man popen

Related

Shared memory ignores read only flag in Linux c

I'm using shared memory with shmget and shmat for educational purpose.
I'm trying to make a memory chunk to be mutable only by it's creator and all other processes can read only.
But the reader processes can somehow write without any error.
This is my code for the creator of the shared memory:
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
int main(){
int shmid = shmget((key_t)56666, 1, IPC_CREAT | O_RDONLY);
if (shmid ==-1) {
perror("Err0:");
exit(EXIT_FAILURE);
}
void* shmaddr = shmat(shmid, (void *)0,0);
if (shmaddr == (void *)-1) {
perror("Err:");
exit(EXIT_FAILURE);
}
*(char*)shmaddr = 'a';
putchar(*(char*)shmaddr);
while(1);
return 0;
}
And this is my code for the reader:
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
int main(){
int shmid = shmget((key_t)56666, 4, O_RDONLY);
if (shmid ==-1) {
perror("Err0:");
exit(EXIT_FAILURE);
}
void* shmaddr = shmat(shmid, (void *)0,0);
if (shmaddr == (void *)-1) {
perror("Err:");
exit(EXIT_FAILURE);
}
*(char*)shmaddr = 'b';
putchar(*(char*)shmaddr);
return 0;
}
As you can see the reader can edit the memory but no error occures even though I open the memory as read only in the reader and created it with read only flag in the creator of the shared memory.
I have not seen any of O_RDONLY or SHM_RDONLY documented as flags for the shmat(2) system call in the linux or freebsd manual pages. Probably the problem is misuse or a misunderstanding on how it works. More on this at the end, as after trying I see that SHM_RDONLY is the flag you should use to control read only attachment, instead of O_RDONLY (which is of no use here)
Probably you have to specify permission bits in the creation shmget(2) system call to disable access for other user's processes, to implement what you want. With permissions, it does work, or you'd have serious security problems with systems that use shared memory (e.g. postgresql database uses sysvipc shared memory segments)
To my knowledge, the best way to implement is to run the writer of the shared memory segment as some user, and the processes allowed to read it as different users, adjusting the permission bits to allow them to read but not to write on the shared memory segment. Something like having all the processes in the same group id, with the writer process as the user who creates the shared memory segment and the others having only read access, with no permissions to other user ids, would be enough for any application.
shmget((key_t)56666, 1, IPC_CREAT | 0640);
and running the other processes as other different user in the same group id.
EDIT
after testing your code in a freebsd machine (sorry, no linux available, but ipc calls are SysV AT&T unix calls, so everything should be compatible) the creation process stops on error on shmat(2) call with the following message:
$ shm_creator
Err:: Permission denied
most probably because you didn't give permissions on shared memory creation, even to the owner (and I try to imagine you are not developing as root in your machine, are you? ;) )
ipcs(1) shows:
usr1#host ~$ ipcs -m
Shared Memory:
T ID KEY MODE OWNER GROUP
m 65537 56666 ----------- usr1 usr1
and you see there are no permission bits active for the shared memory segment, but it has been created. I have modified your program to, instead of doing busywait in a while(1); loop, doing a non consuming cpu wait with sleep(3600); that will put it to sleep for a whole hour.
shm_creator.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
int main(){
int shmid = shmget((key_t)56666, 1, IPC_CREAT | 0640 );
if (shmid ==-1) {
perror("Err0:");
exit(EXIT_FAILURE);
}
void* shmaddr = shmat(shmid, (void *)0,0);
if (shmaddr == (void *)-1) {
perror("Err:");
exit(EXIT_FAILURE);
}
*(char*)shmaddr = 'a';
putchar(*(char*)shmaddr);
puts("");
sleep(3600);
return 0;
}
which I run as user usr1:
usr1#host:~/shm$ shm_creator &
[2] 76950
a
then I switch to another user usr2, and run:
$ su usr2
Password:
[usr2#host /home/usr1/shm]$ shm_client &
[1] 76963
[usr2#host /home/usr1/shm]$ Err:: Permission denied
and as you labeled it, it happens in the shmat(2) system call. But if I run it as usr1 i get:
usr1#host:~/shm$ shm_client
b
if using SHM_RDONLY as flag in the shm_client.c source file, on running (either as same or different user) I get the following:
usr1#host:~/shm$ shm_client
Segmentation fault (generated `core')
which is expected behaviour, as you tried to write unwritable memory (it was attached as read only memory)
EDIT 2
After browsing online the linux manual pages, there's a reference to SHM_RDONLY to allow to attach a shared memory segment as readonly. No support is offered for write only shared memory segments, otherwise. As it is not documented on freebsd, this option is also available there (the constant is included in the proper include files) and some other imprecisions are found in the freebsd manual (as the use of S_IROWN, S_IWOWN, S_IRGRP, S_IWGRP, S_IROTH and S_IWOTH flags to control the permission bits and no inclusion of #include <sys/stat.h> in the SYNOPSIS of the manual page)
CONCLUSSION
If the SHM_RDONLY is available in your system, then you can use it as a non-preemptive way to disallow write access to you shared memory, but if you want kernel enforced way, you have to switch to the user permission bits approach.

Program in C gives 0sec user time and system time

please explain why the user and system time output is zero seconds and 0% cpu usage.
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main() {
char c;
int in, out;
in = open(“inputfile_name”, O_RDONLY);
out = open(“outputfile_name”, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
while(read(in,&c,1) == 1)
write(out,&c,1);
exit(0);
}
If a program runs sufficiently fast, it may terminate before the long-term system clock (as queried with gettimeofday advances. On some systems, this clock has a precision of just 10 ms, so it's likely that this happens with a very brief program like yours. In this situation, the operating system reports the runtime of your program as 0 as it didn't take any time to run from the point of view of gettimeofday.

c/linux - ftruncate and POSIX Shared Memory Segments

The end goal here is that I'd like to be able to extend the size of a shared memory segment and notify processes to remap the segment after the extension. However it seems that calling ftruncate a second time on a shared memory fd fails with EINVAL. The only other question I could find about this has no answer: ftruncate failed at the second time
The manpages for ftruncate and shm_open make no mention of disallowing the expansion of shared memory segments after creation, in fact they seem to indicate that they can be resized via ftruncate but so far my testing has shown otherwise. The only solution I can think of would be to destroy the shared memory segment and recreate it at a larger size, however this would require all processes that have mmap'd the segment to unmap it before the object will be destroyed and available for recreation.
Any thoughts? Thanks!
EDIT: As requested as simple example
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
int main(int argc, char *argv[]){
const char * name = "testfile";
size_t sz = 4096; // page size on my sys
int fd;
if((fd = shm_open(name, O_CREAT | O_RDWR, 0666)) == -1){
perror("shm_open");
exit(1);
}
ftruncate(fd, sz);
perror("First truncate");
ftruncate(fd, 2*sz);
perror("second truncate");
shm_unlink(name);
return 0;
}
Output:
First truncate: Undefined error: 0
second truncate: Invalid argument
EDIT - Answer: Appears that this is an issue with OSX implementation of the POSIX standard, the above snippet works on a 3.13.0-53-generic GNU/Linux kernel and likely others I'd guess.
With respect to your end goal, here's an open source library I wrote that seems to be a match: rszshm - resizable pointer-safe shared memory.

Get Linux system information in C

I have to check Linux system information. I can execute system commands in C, but doing so I create a new process for every one, which is pretty expensive. I was wondering if there is a way to obtain system information without being forced to execute a shell command. I've been looking around for a while and I found nothing. Actually, I'm not even sure if it's more convenient to execute commands via Bash calling them from my C program or find a way to accomplish the tasks using only C.
Linux exposes a lot of information under /proc. You can read the data from there. For example, fopen the file at /proc/cpuinfo and read its contents.
A presumably less known (and more complicated) way to do that, is that you can also use the api interface to sysctl. To use it under Linux, you need to #include <unistd.h>, #include <linux/sysctl.h>. A code example of that is available in the man page:
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/sysctl.h>
int _sysctl(struct __sysctl_args *args );
#define OSNAMESZ 100
int
main(void)
{
struct __sysctl_args args;
char osname[OSNAMESZ];
size_t osnamelth;
int name[] = { CTL_KERN, KERN_OSTYPE };
memset(&args, 0, sizeof(struct __sysctl_args));
args.name = name;
args.nlen = sizeof(name)/sizeof(name[0]);
args.oldval = osname;
args.oldlenp = &osnamelth;
osnamelth = sizeof(osname);
if (syscall(SYS__sysctl, &args) == -1) {
perror("_sysctl");
exit(EXIT_FAILURE);
}
printf("This machine is running %*s\n", osnamelth, osname);
exit(EXIT_SUCCESS);
}
However, the man page linked also notes:
Glibc does not provide a wrapper for this system call; call it using
syscall(2). Or rather... don't call it: use of this system call has
long been discouraged, and it is so unloved that it is likely to
disappear in a future kernel version. Since Linux 2.6.24, uses of this
system call result in warnings in the kernel log. Remove it from your
programs now; use the /proc/sys interface instead.
This system call is available only if the kernel was configured with
the CONFIG_SYSCTL_SYSCALL option.
Please keep in mind that anything you can do with sysctl(), you can also just read() from /proc/sys. Also note that I do understand that the usefulness of that syscall is questionable, I just put it here for reference.
You can also use the sys/utsname.h header file to get the kernel version, hostname, operating system, machine hardware name, etc. More about sys/utsname.h is here. This is an example of getting the current kernel release.
#include <stdio.h> // I/O
#include <sys/utsname.h>
int main(int argc, char const *argv[])
{
struct utsname buff;
printf("Kernel Release = %s\n", buff.release); // kernel release
return 0;
}
This is the same as using the uname command. You can also use the -a option which stands for all information.
uname -r # -r stands for kernel release

How to modify the number of XFS pre-allocated blocks?

I wrote a simple program and ran the program on ext4 and xfs.
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
int
main(int argc, char *argv[])
{
int fd;
char *file_name = argv[1];
struct stat buf;
fd = open (file_name, O_RDWR|O_CREAT);
if (fd == -1) {
printf ("Error: %s\n", strerror(errno));
return -1;
}
write (fd, "hello", sizeof ("hello"));
fstat (fd, &buf);
printf ("st_blocks: %lu\n", buf.st_blocks);
stat (file_name, &buf);
printf ("st_blocks: %lu\n", buf.st_blocks);
close (fd);
stat (file_name, &buf);
printf ("st_blocks: %lu\n", buf.st_blocks);
return 0;
}
output on ext4:
st_blocks: 8
st_blocks: 8
st_blocks: 8
output on xfs:
st_blocks: 128
st_blocks: 128
st_blocks: 8
Then I explored about xfs and found an option for changing the extent size while running mkfs.xfs.
example: mkfs.xfs -r extsize=4096 /dev/sda1
But still I get the same output on XFS. Can anyone provide more insight on how to change the st_blocks. Thanks in advance.
I found the answer, posting the answer here so that others facing the problem can refer it.
mount -t xfs -o allocsize=4096 device mount-point
The allocsize option is used to tune the buffer size.
What you are seeing is xfs speculative preallocation, which is a heuristic which is used to avoid fragmentation of files as they grow.
For more info, see this FAQ entry.
You are correct that the "-o allocsize=XXX" option disables that heuristic. Your attempt at using "-r extsize=XXX" failed because that option is only for the realtime subvolume, which you are almost certainly not using.

Resources