I'm writing a C program to do various stuff on a Linux system, then shut it down. This program will be started with the command line option init=/path/to/program with PID 1, and because of that, I can't use execl("/sbin/poweroff", "poweroff", NULL);, because the poweroff command doesn't shutdown the system itself, it asks the process with PID 1 to do it. So what code does init use to shutdown the system?
Why doesn't poweroff work?
A number of programs assume the kernel has booted with init as PID 1. On many systems init is a symbolic link to the systemd program; similarly on these systems, poweroff is often a symbolic link to the systemctl program.
In your setup, systemd is never started since you set your custom init=/path/to/program kernel parameter line. This is why the poweroff command doesn't work: systemctl is trying to contact a systemd instance which was never created.
How to power off without systemd.
The reboot function is described in the Linux Programmer's Manual. Under glibc, you can pass the RB_POWER_OFF macro constant to perform the reboot.
Note that if reboot is not preceded by a call to sync, data may be lost.
Using glibc in Linux:
#include <unistd.h>
#include <sys/reboot.h>
sync();
reboot(RB_POWER_OFF);
See also
How to restart Linux from inside a C++ program?
Related
I wanted to know if it is possible to run system commands on computer using raspberry pi pico when plugging it into the USB?
I've tried to do it like a normal C program :
#include "pico/stdlib.h"
#include <stdlib.h>
#include <stdio.h>
int main() {
printf("Start");
stdio_init_all();
char *cmd = "ls";
system(cmd);
return 0;
}
Although printf works very well, system functions (eg: readfile) doesn't work.
Is there any way that i could run some kind of actions on PC using pico usb output ?
Also, there is a project called picoducky which allows the pico to run commands on system but unfortunately it has written in python and i'm looking for c code.
Pico communicates with Pc using usb-to-serial and vice versa. Unless there is a server on Pc that interprets data send through serial than executes a cmd command, its not possible with the convetional way. However, you can make Pico emulate a USB HID device and send keystrokes. Check Tinyusb and this pico-superkey-board project
To be able to run system() function call in C in an embedded system, you need to know several things first:
system() calls the user shell with the string passed as argument as a parameter. Are you running an operating system at all? A shell is normally an operating system component, and it is not normally present in many embedded systems.
system() requires /bin/sh normally to work. To run ls, you need in adition to have it (the ls command) installed.
You don't say what operating system you have in your Raspberry pi pico, but I'm afraid it is not linux (or any unix flavour) so probably all of this is forbidden to you.
Normally, the requirements to have a unix like environment in a small system impede to use a high technology operating system in such systems. Linux requires large amoutns of memory (as there are in the normal raspberry pi, but not in the small versions), a large capacity storage system (bein a usb disk, flash memory card, etc. but normally several Gb for a minimum installation)
In your case, 264kb of ram are very small to have a non-mmu handled microprocessor, capable of addressing virtual memory spaces. Also 2Mb of flash gives you to write large programs, but not to install an operating system like linux.
Had you an emulator of system() you should be able to run other programs, but how? A raspberry pi pico has space to run just one program (the one you write to the flash and nothing else) Even if you write a kernel of a multitasking operating system, you would lack space to run filesystem stored programs, as you normally have limited access to the flash where programs are installed.
I have a process running on a very weak Linux embedded device, which could not run gdb / gdb server on itself. I let it provoking a function X from a shared library repeatedly (there are also some others process calling it at the same time with much less frequency), it usually hangs somewhere inside the shared library after 1 day or a half-day. How do I debug:
In case it blocked somewhere: which is the last line of code it ran?
In case it stuck in an infinite loop: which lines of code it running?
What I tried:
I dig into the shared library and put a lot of syslog inside to check. However, with a very high amount of syslog being called constantly, my process now hangs every 2-5 minutes. I think syslog is blocked by UNIX socket?
gdb comes with a program called gcore, which will generate a core file from the running process.
Many systems nowadays disable core files by default (ulimit -c in a shell will show 0). Use the ulimit -c unlimited shell command, then run your process in the same shell (these limits are inherited from the parent process. If you start your process some other way than directly from the shell, you will need to find out how to set them there. e.g., LimitCORE= in a systemd unit file).
Once your process gets into the bad state, run gcore on its process ID. You can then copy it to your workstation and load it into gdb (gdb <executable> <core-file>). You can then view the stack trace and other state as of the moment the core dump was taken.
I have a TCP server application which occasionally needs to reconfigure the bound ports by closing them and then opening them at a later time.
The application also needs to execute an external binary with communication to it. This is currently done using a popen() call. The external binary run time can span the period when the network ports need to be reconfigured.
The problem is, when the main application closes a port it is taken on by the 'forked' process which popen has created to run the binary.
That makes sense (it's discussed at What happens when a tcp server binds and forks before doing an accept ? Which process would handle the client requests? ), but is undesirable, as the main application is then unable to reopen the port.
Is this where FD_CLOEXEC O_CLOEXEC as available in popen(3) can be used? The application needs the pipe that popen(3) offers as stdin to the binary which is executed, is that filehandle left open when CLOEXEC closes the others.
Is there a better way to run the binary, which won't result in a forked process which will hold on to a closed port?
There is another, possibly related question at How to fork process without inheriting handles?
No, you cannot start another program and get back from it without fork(2) followed by some execve(2) code (which is what popen, posix_spawn, and system are doing). You'll better avoid popen or system and code the pipe+fork+execve explicitly yourself (since you know which file descriptors should be kept and which to close(2), generally after the fork and before the execve in the child process...), see this.
(every process & program, except /sbin/init and some hotplug things, is started with fork + execve; and your shell is constantly using fork + execve for most commands, except the builtin ones like cd)
the fork(2) call could be implemented by clone(2).
Read some good book like the Advanced Linux Programming book freely available online here. See also syscalls(2). Use (at least for debugging and to understand things) strace(1) and your debugger (gdb). Study the source code of popen and of system in your free software libc (GNU libc or musl-libc), and the source code of your shell.
You could nearly mimic execve(2) by a tricky sequence of mmap(2) (and related munmap) calls, but not quite (in particular w.r.t. close-on-exec etc...). You'll probably need also to call the obsolete setcontext(3) (or write the equivalent assembler code).
You might consider communicating with a specialized shell-like server-like program doing the fork & execve (see my execicar.c for example and inspiration). Maybe you'll find daemon(3) useful.
A better alternative might be to embed some interpreter (like lua or guile) in your application and/or to dlopen(3) some plugin. The disadvantage is that a bug (in the interpreted script or the plugin) affects your entire server.
You can definitely use the close-on-exec flag to avoid newly started processes inheriting open files or sockets (and there's no other way I'm aware of). If you open a file with open(2) you can set the flag at that moment by adding O_CLOEXEC to the file creation flags. If the file is already open you can set it using fcntl() (and if you opened the file using fopen(3) you can get the file descriptor required for this via fileno(3)). For a socket you can also set the flag when opening it with socket(2) by setting SOCK_CLOEXEC. No file with this flag set will be inherited by a process spawned by your program, be it directly via fork + exec or any other "disguise" of that combination, like system(3) or popen(3).
For example, in a linux-machine there are so many process.
Each one is able to use a syscall, but usually few are used.
Well, there is a tool or a manner to show when a syscall is used and which is the process associated?
You can use various tools, like strace, ltrace and many other, although I'm not sure you want to trace all processes at the same time.
Normally you'd attach to one process of interest and follow its system calls.
You can use Linux kernel audit subsystem.
For example, to see all syscalls made by a program called sshd (pid - 12345):
# auditctl -a entry,always -S all -F pid=12345
Is there any other way to execute a program using kernel, other than shell and system calls?
It always used to be the case that there was really only one way to execute a program on Unix and its derivatives, and that was via the exec() system calls. The very first (kernel) process was created by the boot loader; all subsequent processes were created by fork() and exec(). Of course, fork() only created a copy of the original program; it was the exec() system call - in one of a number of forms in the C source code, but eventually equivalent to execve() - that did the donkey work of replacing the current process with a new image.
These days, there are mechanisms like posix_spawn() which might, or might not, use a separate system call to achieve roughly the same mechanism.
A lot of kernels has support for adding kernel modules or drivers at run time. If you want to execute some code from kernel space (probably because you need higher privileges), you can write a kernel module/driver of your own and load it to execute your code. However, inserting a driver only doesn't ensure that your code will be executed. Based on your driver implementation, you will have to have some triggering mechanism for executing your code in kernel space.
yeah, you can compile your kernel with your program sourced in it, but it won't be the smartest thing to do.
Every program is internally executed by Kernel. If you are looking for running kernel module, you have to use the system calls to reach that module and perform some work for you in Kernel mode. Kernel is event driven and only system calls trigger execution of its modules (apart from some system events like network packet received)