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.
Related
I am trying to understand direct I/O. To that end I have written this little toy code, which is merely supposed to open a file and write a text string to it:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char **argv) {
char thefile[64];
int fd;
char message[64]="jsfreowivanlsaskajght";
sprintf(thefile, "diotestfile.dat");
if ((fd = open(thefile,O_DIRECT | O_RDWR | O_CREAT, S_IRWXU)) == -1) {
printf("error opening file\n");
exit(1);
}
write(fd, message, 64);
close(fd);
}
My compile command for Cray and GNU is
cc -D'_GNU_SOURCE' diotest.c
and for Intel it is
cc -D'_GNU_SOURCE' -xAVX diotest.c
Under all three compilers, the file diotestfile.dat is created with correct permissions, but no data is ever written to it. When the executable finishes, the output file is blank. The O_DIRECT is the culprit (or, more precisely I guess, my mishandling of O_DIRECT). If I take it out, the code works just fine. I have seen this same problem in a much more complex code that I am trying to work with. What is it that I need to do differently?
Going on Ian Abbot's comment, I discovered that the problem can be solved by adding an alignment attribute to the "message" array:
#define BLOCK_SIZE 4096
int bytes_to_write, block_size=BLOCK_SIZE;
bytes_to_write = ((MSG_SIZE + block_size - 1)/block_size)*block_size;
char message[bytes_to_write] __attribute__ ((aligned(BLOCK_SIZE)));
(System I/O block size is 4096.)
So that solved it. Still can't claim to understand everything that is happening. Feel free to enlighten me if you want. Thanks to everyone for the comments.
Well, you need to rethink the question, because your program runs perfectly on my system, and I cannot guess from it's listing where the error can be.
Have you tested it before posting?
if the program doesn't write to the file, probably a good idea is to see about the return code of write(2). Have you done this? I cannot check because on my system (intel 64bit/FreeBSD) the program runs as you expected.
Your program runs, giving no output and a file named diotestfile.dat appeared in the . directory with contents jsfreowivanlsaskajght.
lcu#europa:~$ ll diotestfile.dat
-rwx------ 1 lcu lcu 64 1 feb. 18:14 diotestfile.dat*
lcu#europa:~$ cat diotestfile.dat
jsfreowivanlsaskajghtlcu#europa:~$ _
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.
I recently tried Sysdig for a project.
My main goal is to catch syscalls from the kernel and Sysdig seems to be a good option. Actually, I had done some tests with different techniques and compared the overhead for each one.
I come here with a simple test: a C program which just opens, writes and then close a file 100000 times.
#include "stdio.h"
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
int main(void)
{
int i;
char puffer[100];
FILE * handle;
for (i=0; i<100000; i++) {
strcpy (puffer, "Sysdig c'est trop fort !\n");
handle = fopen("test.txt", "w");
fputs(puffer, handle);
fgets(puffer, 80, handle);
fclose(handle);
}
return 0;
}
I ran 5 tests without supervision and the average duration is:
real: 30,29s
user:1.068
sys:13.098
I ran other 5 tests with small LKM with kprobes. It took about 3 more seconds to complete the same test.
At this point, everything seems normal but when I ran tests with Sysdig:
sudo sysdig proc.name="ctest" > ctestlog
Where ctest is my C program, I had those results on average:
real: 17,1108
user: 0,6336
sys: 7,3752
So the result from this tests is that Sysdig enhanced my process quite by twice.
I precise that standard deviation from my tests is less than 1 sec.
Has someone already seen something like that or have an explanation?
Can it be related with linux task scheduler because of Sysdig job?
I have very simple code that should run on background and at 1 am shut down the computer:
#include <ctime>
#include <cstdlib>
#include <unistd.h>
int main() {
time_t t;struct tm * now;
daemon(0,0);
while(1){
t = time(0);
now = localtime( & t );
if(now->tm_hour==1){
system("shutdown -P");
break;
}
sleep(10);
}
return 0;
}
The code works without sleep(10) but uses whole free memory so I need sleep function there to stop loop and recheck time each ten seconds, but with sleep function program stops immediately after I run it.
If you are writing C code, don't use C++ headers (ctime, cstdlib). Replace those #includes with #include <stdlib.h> and #include <time.h>. If the behavior of this code is really as you describe (which I would find surprising), then this is probably the source of the error.
Of course it immediately exits. Thats the whole point of using daemon. Check with ps and you will see that your proram is still running as a seperate process now.
Check the man page for a desription how daemon works.
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