I wrote a small program “Zeichnen” with qt and ported it to QNX neutrino 6.5.0 SP1 (for BeagleBoard xM).
It is working just fine
Now I want to start this program from my C Code. I want the new program to run separately, like if I start in Linux a program with “&”. For this I tried the following:
(I borrowed some code from a tutorial)
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char *argv[])
{
pid_t kind1;
while(1)
{
switch(kind1=fork())
{
case -1 : printf("Fehler bei fork()..........\n"); exit(0);
case 0 : printf("Kindprozess: Mein PID ist %d\n",getpid());
printf("Kindprozess: Meine Eltern haben die PID %d\n",getppid());
execl ("/Zeichnen/Zeichnen", "zeichnen", "-qws", "&");
printf("Überschreibe prozess");
exit(1);
default : printf("Elternprozess: Ich habe folgendes Kind PID : %d\n",kind1);
printf("Elternprozess: Meine PID lautet %d\n",getpid());
printf("Elternprozess: Die PID meiner Eltern lautet %d\n",getppid());
exit(2);
}
}
return EXIT_SUCCESS;
}
This is the output:
Elternprozess: Ich habe folgendes Kind PID : 442402
Elternprozess: Meine PID lautet 442390
Elternprozess: Die PID meiner Eltern lautet 151579
Kindprozess: Mein PID ist 442402
Kindprozess: Meine Eltern haben die PID 442390
Ü
I cannot understand what is happening… the childprocess is started, but the execl-command and the print-command are ignored (print command only the first letter), what is the problem?
Is this not the correct way? What else could I do?
What is my goal:
starting different programs on the Board via the serial interface from another program on my pc (and stopping of course… with kill() )
with a NULL argument and it is starting now BUT:
I overwrite the actual process (correct?), so I still have the problem with fork()-process and that it runs seperate from its parent process
‘&’ is a signal to the shell to run a program in the background. It is not usually an argument to a program the way you are doing this. I would take a look at spawn() and it’s variants, eg. spawnl().
Yeah, I know that “&” is normaly used in the shell only.
… You could say that was a try out of frustration + not so much knowledge about unix systems (but I am learning)
Thx 4 answer, I will check the suggested spawn()-function.
Now I want to stop/kill this new process → what command can I use in my code for this?
I find a lot about wait() and such, but that is only if the child is stopping and the parent is reacting to it.
I want the parent to stop a process (in my case a process which is running simultaneously with the parent process).
I know that this is not a good way, but it is only for testing
Edit:
I found the function
int SignalKill( uint32_t nd, pid_t pid, int tid, int signo, int code, int value );
and I tihink this could help me, but can someone explain me what “code” and “value” would be?
Maybe I am just blind, but I cannot find an example or an explanation in the documents about what value I should enter here.
I tried with
SignalKill( 0, pid, 0, SIGKILL,0, 0 );
→ Now the process seems to stop, but i doesn´t vanish from the list. Instead there stands “unavailable” and it only vanishs if I stop the parent.
Could it be a Zombie? → How can I get rid of this? (waitpid() also stops my parent after the kill signal)
You are getting the Zombie because the child process dies and it trying to notify the parent of it’s final error code.
The Zombie is what is left of the process. No memory, but just an error code. It does take up a space in the process list which could eventually fill up if you get enough zombies. To fix this you have three choices.
Let the parent die.
Do a wait() or waitpid() in the parent. This will return the error code and the Zombie will go away.
Use the SPAWN_NOZOMBIE flag if you are using spawn(). If instead you are using spawnl() you can use the P_NOWAITO flag instead of P_NOWAIT.
@Tim:
I have also seen the system()-command, but for this I need the shell “sh” (as far as I know).
But this sh-process is disrupting my serial interface connection with my Pc, so I kill this process after booting.
→ I am using a demoOS from QNX with the librarys that I need already implemented, because I have problems in understanding how to build the binary from commandline with Qt.
It would be nice if someone can explain me this, but I think I will start a new thread for this (with better explanation)
@maschoen:
I tried Nr.2 already with waitpid() but then the parent also stops?
P_NOWAITO is a good suggestion, I will try this later
spawnl() is working the way I wanted with my testprogram. Now I tried to create processes with different programs and got an error which I don´t know how to fix it.
I made a testprogram named “QMLTest” and, as the name implies, it is a Qt QML program.
The folderstructure looks like this on my Beagleboard (the folders are outside of the OS-binary):
(/ (root) -> doesn´t stand there, but as far as I know is there :) )
-> bin
-> ramdisk
-> and so on..
.
.
.
-> QMLTest
-> QMLTest (binary)
-> content
-> QMLTest.qml
-> circle.png
-> arrow.png
In short: In the folder QMLTest are the binary from the Qt-project and a subfolder “content” with the qml-file and the used pictures.
If I use the shell to call this process
cd /QMLTest
./QMLTest -qws &
It is working fine (also if I am in the folder and only call “QMLTest -qws” ).
But if I use
I start my QNX program only temporary in /ramdisk (found a paper which told me so) and therefore it cannot find the subfolder (this is my guess). Does this mean I have to use spawnl() in the folder where the other program is located?
I also have this problem with another program which is using picures! (then the error is like: “Picture is a null-image”).
I wanted to start process according to the buttons you press on a GUI.
For the QMLTest program it is working. But for another program “Vererbung” it is not working.
For this program I use png-pictures in a folder “Bilder”. The structure is nearly the same as “QMLTest”:
Replace the Qt load with an fopen() to see if you can open the file. If you can, then the problem is with the Qt routine. If you can’t open it, either the file is corrupt or you have a permissions problem.
this program is running without problems if I use the shell to start the process.
Does this mean, if fopen can open the picture, that the shell and the spawnl() command have different permission “levels” ?
(Still haven´t the time to test fopen…)
Different users can have different permissions on files.
If fopen() can’t open the file, then you would not expect the routine to be able to either.
If fopen() can open the file, then there isn’t a file permission problem, so the problem is likely with the use of the Qt routine.
Finally I had time to test fopen(). For this I added
printf("%s\n", "opening with fopen()");
datei = fopen("/Vererbung/Bilder/Zeiger.png", "r");
if(datei == NULL)
{printf("%s\n", "opening with fopen() not working");}
else
{printf("%s\n", "opening with fopen() ok!");}
to my Qt Code. The result ist this:
So like maschoen said, there should be some problems with my Qt-routine, BUT this program is running on the same board and QNX if I don´t use spawnl(). Instead if I use the momentics suit to start the binary or the shell then it is ok and the pictures are found.
In my case I stopped the shell because it disturbs my communication.
If I now want to start a new program with the pictures, then this program doesn´t have the environment variables it needs.
Possible ways to fix this:
1.
Using systems() as it starts a new shell and don´t disturb my communication IF I add “&” AND the command doesn´t read/write stdin/stdout.
I still need the environment variables and can set it with a script started via system() → system("/directory/script");
I used spawnle() instead of spawnl() and set the environment variable with a char-array