running executable files turn to be empty files when suddenly power off - c

I have two executable files, whose source like below:
main_a.c
#include "stdio.h"
int main() {
printf("start to copy\n");
system("cp -pRf ~/main_b main_b");
system("cp -pRf ~/main_a main_a");
printf("done\n");
}
main_b.c
#include "stdio.h"
int main() {
while (1) {
printf("i'm b, i'm running\n");
}
}
gcc -o main_a main_a.c
gcc -o main_b main_b.c
then I put main_a and main_b in ~ and ~/test.
I cd in ~/test, running main_b in background like this
./main_b 1>/dev/null &
and run main_a in foreground link this
./main_a; sleep 100
wait a while, unplug the power, then reboot, i get two files whose size is zero and has no content in ~/test.
Anybody knows why?
PS:
to ensure file has been replaced, i touch ~/test/main_a and ~/test/main_b two hours ago and watch, then unplug the power.
touch -d "2 hours ago" ~/test/*

You should check the result code of each system(3).
And I would suggest calling sync(2) at the end of function main in main_a.c

Related

how to get rid of the "unknown" section in the perf

what I did is:
1. sudo rm -rf /root/.debug/
2. compile program with -g -O2 -fno-omit-frame-pointer
3. run the program and get the pid
4. sudo perf record -F 2000 -a -s -g -p $pid sleep 15
5. sudo perf report
then I get a tiny part of "unknown", like
- 2.50% 0.00% postgres [unknown] [k] 0000000000000000
- 0
1.12% _int_malloc ▒
0.79% _IO_vsnprintf
looks this is due to libc 'malloc' call. then I write a program on the same machine to test it.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
int main(int argc, char *argv[])
{
while(1) {
printf("perf record -g -p %d -- sleep 5; perf report\n", getpid());
sleep(1);
void *p = malloc(10);
memset(p, 0, 10);
free(p);
}
return 0;
}
then I did the same thing as above, there is no "unknown" section.
how to explain/fix this?
The [unknown] block in the perf report output refers to the name of the dynamic shared object (DSO). perf report could not resolve the DSO path and hence it prints [unknown]. Per the latest kernel source code tree (which is 5.3.9 at the time of writing), you can see this here.
It is important to know that the determination of the DSO symbols happen with the help of the sampled event address. The function thread__resolve is responsible for doing exactly that. In older kernels, the thread__resolve method had another name - perf_event__preprocess_sample_addr.
Given the snapshot of your output, it looks like the address of the event that was sampled during perf record, is 0. This means that the address could not be resolved at all. It is an address in the kernel space (looking at the symbol [k] 0000000000000000) and perf in your case, could not resolve it.
The comments highlight setting perf_event_paranoid to a suitable value so that you can probe both kernel and user-space events successfully. Setting perf_event_paranoid to a value that allows you to correctly probe events in the kernel space should "be a step" towards correctly resolving the address.

Problem with new System call I'm trying to make (Ubuntu 18.04.1 LTS Kernel:4.17.4)

These are the steps I followed.
1) I was running on 4.15.0 kernel so I updated to more recent kernel.
wget https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.17.4.tar.xz
2)Extracted the kernel source code using
sudo tar -xvf linux-4.17.4.tar.xz -C/usr/src/
3) In cd /usr/src/linux-4.17.4/ created a new directory called it
sub
Then created
sub.c
inside
sub
directory.
In
sub.c
I wrote the code to subtract y from x if (y>x) or else return 0; Here x is Integer and y is double.
#include <linux/kernel.h>
asmlinkage int sys_sub(int x,double y)
{
printk("working...");
if(y>x){
return ((int)y-x);}
else
return 0;
}
4) created a Makefile in the same sub directory and added obj-y := sub.o
5) In
/usr/src/linux-4.17.4
opened Makefile and modified the core-y line to
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ sub/
6) Then in
cd arch/x86/entry/syscalls/
I opened
gedit syscall_64.tbl
and as 548th system call I entered
548 64 hello sys_sub
7) In
cd include/linux/
I opened
gedit syscalls.h
and added
asmlinkage int sys_sub(int x,double y);
as the last line just before endif
8) I made sure ext4 is chosen in
sudo make menuconfig
9) I compiled the kernel using
sudo make modules_install install
10) performed
shutdown -r now
11) Checked
uname -r
to make sure that I'm running
4.17.4
indeed which I was.
12) I created a C program to check the system call
#include <stdio.h>
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>
int main()
{
int res = syscall(548,10,44);
printf("System call sys_sub returned %d ", res);
return 0;
}
But it is only returning
System call sys_sub returned 0
and
dmesg
shows Hello World for some reason. Please help me. What am I doing wrong?
Edit:
I made necessary changes in my code as per the comments I read.
Now my system call code looks like this:
#include <linux/kernel.h>
asmlinkage long sys_sub(int a,int b)
{
printk("System call is working...\n");
printk("Inputs are %d and %d",a,b);
if(b>a)
{
int c= b-a;
printk("Answer is %d",c);
return c;
}
printk("Answer is 0");
return 0;
}
I added some print statements to make sure that the system calls are correctly invoked.
I recompiled the kernel and ran again and now I'm getting
dmesg
output as
System call is working... Inputs are 1114685272 and 1114685272 Answer
is 0
Seems like the kernel is getting random junk values instead of the parameters that I'm passing which makes it to always fail the if loop. The random values for both parameters seems to always be the same!
I dont know where I'm going wrong now.
In one internet article it is mentioned to compile whole kernel and then modules_install. Also return of system call has to be long instead of int. unistd.h file needs some changes for new system call.
The article is for 2.6 kernel but can be referred at http://www.tldp.org/HOWTO/html_single/Implement-Sys-Call-Linux-2.6-i386/

compiling and running a c program using exec()

I am writing a program using execv() that compiles and runs another program. I've written up a simple C program named helloWorld.c that when executed outputs, "Hello world," and a second file named testExec.c that is supposed to compile and run helloWorld.c. I've been looking around everywhere to find a way to do this, but I haven't found any answers. The code in testExec.c is:
#include <stdio.h>
#include <unistd.h>
int main(){
char *args[] = {"./hellWorld.c", "./a.out", NULL};
execv("usr/bin/cc", args);
return 0;
}
testExec.c compiles with no errors. However, when I run it I get an error that says, "fatal error: -fuse-linker-plugin, but liblto_plugin.so not found. compilation terminated." Which I think means helloWorld.c is being compiled but when it comes time to run helloWorld.c this error is thrown. I thought maybe that was because I had a.out and helloWorld.c prefaced with './'. I removed './' from both, then either one individually, and still no luck.
I also did 'sudo apt-get install build-essential' along with 'sudo apt-get install gcc'. I wasn't sure if that would resolve the issue but I really wasn't sure what else to try. Anyway, any help would be appreciated!
You're missing the leading slash when calling cc.
Also, the first argument in the argument list is the name of the executable. The actual arguments come after that. You're also not using -o to specify the name of the output file.
#include <stdio.h>
#include <unistd.h>
int main(){
char *args[] = {"cc", "-o", "./a.out", "./hellWorld.c", NULL};
execv("/usr/bin/cc", args);
return 0;
}
EDIT:
The above only compiles. If you want to compile and run, you can do this:
#include <stdio.h>
#include <unistd.h>
int main(){
system("cc -o ./a.out ./hellWorld.c");
execl("./a.out", "a.out", NULL);
return 0;
}
Although this is probably best done as a shell script:
#!/bin/sh
cc -o ./a.out ./hellWorld.c
./a.out

struct timespec used in multiple source files: C

new user so I'm sorry if this explanation isn't clear enough...I am having trouble creating timespec variables to be modified/used between multiple source files. My program is meant to determine the time it takes to execute another program from within my initial program and therefore I'll need to clock the time in two source files and store it to be used later to determine the difference in time. I have been scouring the internet and tried different things but it always seems like my source files create different instances of the variables
Here's what my code basically looks like:
Header file:
//shared.h
#ifndef shared_h
#define shared_h
#include<time.h>
extern struct timespec callTime, startTime;
#endif
Source File1:
//shared.c
#include "shared.h"
struct timespec startTime = {0}, callTime = {0};
Source File2:
//app.c
#include "shared.h"
#include <time.h>
void main(){
clock_gettime(CLOCK_MONOTONIC, &startTime);
}//end of main
Source File:
//timer.c
#include "shared.h"
#include <time.h>
void main(){
pid_t pid = fork();
clock_gettime(CLOCK MONOTONIC, &callTime);
if(pid == 0){
execvp("./app", NULL);
return 0;
}//end of if
printf("Call: %ld & Start: %ld\n", callTime.tv_sec, startTime.tv_sec);
return 0;
}//end of main
I will get something like...
Call: 14928304940 & Start: 0
Hopefully this code gets the point across of what I'm trying to do. When it forks and executes the other program, the value for startTime will change but won't hold so that when I call it later in the Parent process. The value will just be it's initial value instead of the clocked time. it seems Any thoughts on the matter would be greatly appreciate!
Added Note: I do link shared.c with timer.c and app.c seperately and then run timer.c
gcc shared.h
gcc -c shared.c
gcc -c app.c
gcc -c timer.c
gcc -o app app.o shared.o
gcc timer.o shared.o
./a.out
I think your problem here is a misunderstanding of what fork does. It gives the child process a copy of the parent processes memory. Not the same memory.... well actually on sane architectures it IS the same memory w/o copy-on-write semantics, but don't worry about that for now.
Your child process (assuming app.c compiles to app here) will modify its own copy of startTime then exit w/o modifying the parent processes startTime variable.
If you want to have the child process communicate something back to the parent, you need to use some form of interprocess communication.
What you're trying to do won't work. Sharing variables like that only works when multiple source files are linked into the same executable, and even then only for a given running process.
You'll need to have the child process send a message back to the parent when it starts, preferably via a pipe, at which time the parent knows when the child started and can call clock_gettime a second time.

Missing Symbol during Runtime in Over-The-Air Programming Code

I am currently working on developing over-the-air programming support on sky motes. Attached are the files that I have so far. I am basically trying to use the sky-shell-exec example to load my modified test-deluge.ce file onto the mote. I then try to run the test-deluge file using the shell 'exec' command as done in the sky-shell-exec example.
The final goal is to load both the test-deluge.ce and hello-world.ce compiled files onto the mote and then be able to 'exec' my test-deluge.ce file which would then find the stored hello-world.ce file and do a deluge_disseminate on it.
The progression of command I am running are as follows:
1) sudo make TARGET=sky clean CLEAN=symbols.?
2) sudo make sky-shell-exec.sky TARGET=sky
3) sudo make sky-shell-exec.sky CORE=sky-shell-exec.sky TARGET=sky
4) sudo make sky-shell-exec.upload CORE=sky-shell-exec.sky
5) sudo make compile-test-deluge-executable
6) sudo make upload-test-deluge-executable
7) sudo make login
8) ls (to see that the file made it)
9) exec test-deluge.ce
At this point I get a 'Symbol not found: deluge_disseminate' error
I believe the error is in the 'CORE=...' part of the make (in step 2 above). I have inspected the symbols.c file that is filled out in step 2 of the above and indeed there is no symbol for deluge_disseminate or any of the deluge commands for that matter that I recall.
For experimentation I tried the following:
sudo make test-deluge.sky TARGET=sky
sudo make test-deluge.sky CORE=test-deluge.sky TARGET=sky
and I find that the symbols for deluge are there, but I can't proceed to properly make sky-shell-exec file since doing so erases the symbols table and writes a new one.
I feel like there must be a simple fix to this as I can run hello-world from the sky-shell-exec example directory after following the above steps (1-9).
Does anyone have an idea of how to go about this?
NOTE: There may be a bug in my test-deluge.c where I try to open 'hello-world.sky' instead of 'hello-world.ce'...I wasn't really sure which one. I haven't been able to test this yet because of the missing symbol issue explained above, but if anyone would be willing to shed light on this issue as well I would be very appreciative.
Thanks
MAKEFILE
CONTIKI = ../..
ifndef TARGET
TARGET=sky
endif
APPS = deluge serial-shell
all: blink sky-collect #rt-leds test-button test-cfs tcprudolph0
#all: $(CONTIKI_PROJECT)
%.tgz: %.ihex
mkdir $(basename $<) ; \
mv $< $(basename $<) ; \
echo $(basename $<)/$(basename $<).ihex 600 > $(basename $<)/runfile ; \
tar czf $# $(basename $<)
%.class: %.java
javac $(basename $<).java
viewrssi: ViewRSSI.class
make login | java ViewRSSI
include $(CONTIKI)/Makefile.include
%.shell-upload: %.ce
(echo; sleep 4; echo "~K"; sleep 4; \
echo "dec64 | write $*.ce | null"; sleep 4; \
../../tools/base64-encode < $<; sleep 4; \
echo ""; echo "~K"; echo "read $*.ce | size"; sleep 4) | make login
.PHONY: compile-test-deluge-executable upload-test-deluge-executable compile-hello-world-executable upload-test-deluge-executable
compile-hello-world-executable: hello-world.ce
echo Compiled Contiki executable: $<
upload-hello-world-executable: hello-world.shell-upload
echo Uploaded Contiki executable: $<
compile-test-deluge-executable: test-deluge.ce
echo Compiled Contiki executable: $<
upload-test-deluge-executable: test-deluge.shell-upload
echo Uploaded Contiki executable: $<
sky-shell-exec.c
#include "contiki.h"
#include "shell.h"
#include "serial-shell.h"
#include "deluge.h"
#include "dev/watchdog.h"
#include "net/rime.h"
#include "dev/cc2420.h"
#include "dev/leds.h"
#include "dev/light.h"
#include "dev/sht11.h"
#include "dev/battery-sensor.h"
#include "lib/checkpoint.h"
#include "net/rime/timesynch.h"
#include <stdio.h>
#include <string.h>
int (*keep_1)(void) = deluge_disseminate;
int (*keep_2)(void) = node_id_burn;
/*---------------------------------------------------------------------------*/
PROCESS(sky_shell_process, "Sky Contiki shell");
AUTOSTART_PROCESSES(&sky_shell_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(sky_shell_process, ev, data)
{
PROCESS_BEGIN();
serial_shell_init();
/*shell_blink_init();*/
shell_file_init();
shell_coffee_init();
/*shell_ps_init();*/
/*shell_reboot_init();*/
/*shell_rime_init();*/
/*shell_rime_netcmd_init();*/
/*shell_rime_ping_init();*/
/*shell_rime_debug_init();*/
/*shell_rime_sniff_init();*/
/*shell_sky_init();*/
shell_text_init();
/*shell_time_init();*/
/* shell_checkpoint_init();*/
shell_exec_init();
shell_base64_init();
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
test-deluge.c
#include "contiki.h"
#include "cfs/cfs.h"
#include "deluge.h"
#include "sys/node-id.h"
#include "loader/elfloader.h"
#include <stdio.h>
#include <string.h>
#ifndef SINK_ID
#define SINK_ID 1
#endif
#ifndef FILE_SIZE
#define FILE_SIZE 1000
#endif
PROCESS(deluge_test_process, "Deluge test process");
AUTOSTART_PROCESSES(&deluge_test_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(deluge_test_process, ev, data)
{
static struct etimer et;
node_id_burn(2);
PROCESS_BEGIN();
if(node_id == SINK_ID) {
printf("Sink node: trying to transmit file.\n");
} else {
printf("Non-sink node: trying to recieve file.\n");
}
cfs_remove("hello-world.sky");
int fd = cfs_open("hello-world.sky", CFS_WRITE | CFS_READ);
if(fd < 0) {
process_exit(NULL);
}
#if 0
if(cfs_seek(fd, FILE_SIZE, CFS_SEEK_SET) != FILE_SIZE) {
printf("failed to seek to the end\n");
}
#endif
deluge_disseminate("hello-world.sky", node_id == SINK_ID);
cfs_close(fd);
etimer_set(&et, CLOCK_SECOND * 5);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
if(node_id != SINK_ID) {
fd = cfs_open("hello-world.sky", CFS_READ);
if(fd < 0) {
printf("failed to open the test file\n");
} else {
printf("Start dynamic loading\n");
int ret = elfloader_load(fd);
printf("%d\n", ret);
cfs_close(fd);
int i;
switch(ret) {
case ELFLOADER_OK:
for(i=0; elfloader_autostart_processes[i] != NULL; i++) {
printf("exec: starting process %s. \n",
elfloader_autostart_processes[i]->name);
}
autostart_start(elfloader_autostart_processes);
break;
default:
printf("Unkown return code from ELF loader (internal bug)\n");
break;
}
}
}
etimer_reset(&et);
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
hello-world.c
#include "contiki.h"
#include <stdio.h> /* For printf() */
/*---------------------------------------------------------------------------*/
PROCESS(hello_world_process, "Hello world process");
AUTOSTART_PROCESSES(&hello_world_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(hello_world_process, ev, data)
{
PROCESS_BEGIN();
printf("Hello, world\n");
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
So with great help from the contiki community I was able to gather the following solution:
"Hi,
The problem is that the build system of Contiki tries to "act smart"
and excludes symbols the application apparently does not need. So in
this case the deluge_disseminate function code is optimized away from
sky-shell-exec executable. Obviously, this conflicts with the basic
intuitions that the programmer has in case of over-the-air
programming.
To work around this issue, add a reference to deluge_disseminate in
sky-shell-exec code. For example, add this line (at global scope):
int (*keep)(void) = deluge_disseminate;
You can also try to tweak GCC linker options or use a custom linker script."
Using the same trick for node_id_burn as well, test-deluge.c runs.
The corrections have been made to the above code.
Hopefully this helps anyone else out there who may be struggling with OTA code in Contiki.

Resources