killall

daniel2000lu

Commodore Special
Mitglied seit
17.12.2004
Beiträge
402
Renomée
0
Standort
Luxembourg
Hallo,

Mein Problem ist folgendes :

Ich muss die killall Funktion in C programmieren, leider habe ich keine Ahnung wie ich das machen soll, da mir dies im Kursus zu schnell gegangen ist. Soweit ich verstanden habe soll die funktion kill -9 drin vorkommen.

Kann mir hier bitte jemand helfen?

Danke im Voraus
 
Hallo und Danke für deine Antwort.

Also wir arbeiten ausschliesslich in KDE und ich nehme an dass der killall in der Konsole ausgeführt werden soll.
 
Ok, also unixoides System, vermutlich eine Linux-Distribution. Das nahe liegenste ist da, dass es eine kleine Consolen-Applikation werden soll. Ich vermute jetzt auch mal, dass du hier nicht den Befehl `kill` aufrufen sollst, sondern den entsprechenden syscall nutzen sollst. Die manpage sagt dazu folgendes:

NAME
kill - send signal to a process

SYNOPSIS
#include <sys/types.h>
#include <signal.h>

int kill(pid_t pid, int sig);

Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

kill(): _POSIX_C_SOURCE || _XOPEN_SOURCE

DESCRIPTION
The kill() system call can be used to send any signal to any process group or process.

If pid is positive, then signal sig is sent to pid.

If pid equals 0, then sig is sent to every process in the process group of the current process.

If pid equals -1, then sig is sent to every process for which the calling process has permission to send signals, except for process 1
(init), but see below.

If pid is less than -1, then sig is sent to every process in the process group -pid.

If sig is 0, then no signal is sent, but error checking is still performed.

For a process to have permission to send a signal it must either be privileged (under Linux: have the CAP_KILL capability), or the
real or effective user ID of the sending process must equal the real or saved set-user-ID of the target process. In the case of SIG-
CONT it suffices when the sending and receiving processes belong to the same session.

RETURN VALUE
On success (at least one signal was sent), zero is returned. On error, -1 is returned, and errno is set appropriately.

ERRORS
EINVAL An invalid signal was specified.

EPERM The process does not have permission to send the signal to any of the target processes.

ESRCH The pid or process group does not exist. Note that an existing process might be a zombie, a process which already committed
termination, but has not yet been wait(2)ed for.

CONFORMING TO
SVr4, 4.3BSD, POSIX.1-2001

NOTES
The only signals that can be sent to process ID 1, the init process, are those for which init has explicitly installed signal han-
dlers. This is done to assure the system is not brought down accidentally.

POSIX.1-2001 requires that kill(-1,sig) send sig to all processes that the current process may send signals to, except possibly for
some implementation-defined system processes. Linux allows a process to signal itself, but on Linux the call kill(-1,sig) does not
signal the current process.

POSIX.1-2001 requires that if a process sends a signal to itself, and the sending thread does not have the signal blocked, and no
other thread has it unblocked or is waiting for it in sigwait(3), at least one unblocked signal must be delivered to the sending
thread before the kill().

Linux Notes
Across different kernel versions, Linux has enforced different rules for the permissions required for an unprivileged process to send
a signal to another process. In kernels 1.0 to 1.2.2, a signal could be sent if the effective user ID of the sender matched that of
the receiver, or the real user ID of the sender matched that of the receiver. From kernel 1.2.3 until 1.3.77, a signal could be sent
if the effective user ID of the sender matched either the real or effective user ID of the receiver. The current rules, which conform
to POSIX.1-2001, were adopted in kernel 1.3.78.

BUGS
In 2.6 kernels up to and including 2.6.7, there was a bug that meant that when sending signals to a process group, kill() failed with
the error EPERM if the caller did have permission to send the signal to any (rather than all) of the members of the process group.
Notwithstanding this error return, the signal was still delivered to all of the processes for which the caller had permission to sig-
nal.

SEE ALSO
_exit(2), killpg(2), signal(2), sigqueue(2), tkill(2), exit(3), capabilities(7), credentials(7), signal(7)

Das sollte dir eigenlich schonmal weiter helfen.
 
Hallo,
Vielen Dank für die Antwort.

Leider kann ich mit dem man nicht viel anfangen. War gleich beim 1. Kursus wo dies durchgenommen wurde, und das ging mir zu schnell um mitzukommen. Habe bruchstückhaft mitgeschrieben, doch als ich geschrieben hatte war der schon beim nächsten Kommando, so dass ich leider noch nicht viel schlauer bin.

Kannst du mir das vielleicht auch auf eine sehr vereinfacht Weise erklären? Ist wie gesagt erst der 1. Kursus gewesen...
 
Hallo,
Vielen Dank für die Antwort.

Leider kann ich mit dem man nicht viel anfangen. War gleich beim 1. Kursus wo dies durchgenommen wurde, und das ging mir zu schnell um mitzukommen. Habe bruchstückhaft mitgeschrieben, doch als ich geschrieben hatte war der schon beim nächsten Kommando, so dass ich leider noch nicht viel schlauer bin.

Kannst du mir das vielleicht auch auf eine sehr vereinfacht Weise erklären? Ist wie gesagt erst der 1. Kursus gewesen...

Ok, also ich setze jetzt voraus, dass dir das Konzept der Prozesse bekannt ist. Des weiteren beschränke ich mich in meiner weiteren Ausführung auf Linux bzw. unixoide Systeme. Sollte für deinen Fall ja ausreichend sein.

Grundsätzlich lassen sich an jeden Prozess Signale senden, die vom jeweiligen Prozess behandelt werden können oder sogar müssen, je nach Signal. Wenn du mal eine console öffnest und dort 'man 7 signal' eingibst, bekommst du eine Auflistung aller möglichen Signale und ihre Wirkung ('q' beendet das manual wieder).
Das Kommandozeilenprogramm 'kill' ist nun eine mögliche Implementierung, einem Prozess ein Signal zuzusenden. Im Endeffekt implementiert dies nichts anderes als den passenden Systemaufruf. Die von mir oben zitierte man-page dokumentiert diesen Systemaufruf. Du musst dabei angeben, welchem Prozess du welches Signal senden willst. Die Prozesse werden dabei über ihre eindeutige Prozess-ID (PID) identifiziert.
Das Kommandozeilenprogramm 'killall' geht ein wenig weiter. Dies identifiziert die Prozesse nicht mehr an Hand ihre ID, sondern an Hand des Programmnamens, über den sie gestartet wurden. Die Konsequenz daraus ist jetzt also, dass es mehrere Prozesse mit dem gleichen Namen geben kann, denen alle das jeweilige Signal geschickt werden soll.

Da es aber für killall keinen Systemaufruf wie kill gibt, hast du jetzt die Mehrarbeit, dass du alle Prozesse durchgehen musst, und sie darauf testen musst, ob ihr Name mit dem gewünschten übereinstimmt. Dafür iterierst du über alle Prozesse und vergleichst Name mit deiner Referenz. Stimmen die Namen überein, merkst du dir die jeweilige PID. Am Ende schickst du allen gesammelten Prozessen das entsprechende Signal (9 oder 15).

Das wäre eigentlich die grobe Beschreibung des Handlungsablaufs.
 
Danke.
Jetzt weiss ich endlich mal was genau der killall bedeuted.

Ich muss also ein FOR Suche starten mit der ich die einzelnen Prozesse im ps -fade vergleiche um zu sehen welche mich interessieren. Diese muss ich dann einzeln mit einem system(kill NAME) ausschalten. Sehe ich das richtig so?

Wenn ja, wie kann ich das in C programmieren?
.
EDIT :
.

habe anhand meiner Notizen, soweit wie ich die verstanden habe und anhand des letztens Posts, folgendes ausprobiert. Könnte dies die Lösung sein? Habe leider kein KDE um zu testen :

Datei : mykillall.c

#include <stdio.h>
#include <signal.h>

int main(int argc,char** argv) {

int i;

if (argc != 2)
{printf("falsche Killall - Parameter");}
else
{ kill (system("ps -edf ¦ grep argv[1][]"));

}
}

Dies ist bis jetzt die beste Möglichkeit die mir einfällt. Hoffentlich bin ich wenigstens auf dem richtigen Weg*kopfkratz*zweifel*
 
Du sollst das wirklich in C implementieren? Das sieht mir erstmal ziemlich nach Bash-Script oder Python aus. Davon abgesehen halte ich es für reichlich übertrieben, so etwas von jemanden gleich in der ersten Stunde zu verlangen. Das verlangt zum einen zumindest rudimentäre Kenntnisse in C-Programmierung, zum anderen diverse Grundkenntnisse von Betriebssystemen im Allgemeinen und Unix/Linux im Besonderen.
Ich schau mir das nochmal etwas genauer an, wenn ich Zeit hab. Aus dem Stehgreif kann ich das auch nur bedingt coden.
 
also in C-Programmation haben wir mittlerweile 1 Semester erfahrung, allerdings haben wir erst 2 Stunden Erfahrung mit dem Unix System.

Deshalb weiss ich ja eben nicht so wirklich wie ich das anpacken soll, und zu allem Übel wird das auch noch bewerted ... *traurig*
 
Sicher, dass ihr den "system" befehl benutzen sollt? oder sollt ihr die PID zum namen selbst finden (z.b. über /proc)?
 
ich denke schon dass wir die system Funktion benutzen dürfen, denn von /proc war noch nicht die Rede, und in meinen Notizen kann ich dies auch nirgends finden. Und aufgeschrieben habe ich recht viel
 
ich denke schon dass wir die system Funktion benutzen dürfen, denn von /proc war noch nicht die Rede, und in meinen Notizen kann ich dies auch nirgends finden. Und aufgeschrieben habe ich recht viel

Das ganze ist dennoch nicht so richtig trivial, da du ja noch den Output von 'ps' parsen musst. Irgendwie musst du ihn ja in deinem Programm verwerten können. Die Schwierigkeit beim killall liegt darin, alle Prozesse zu finden, die mit mit dem entsprechenden Kommando gestartet wurden.
 
hmm, vielleicht haben wir noch nicht alles gesagt bekommen was ALLE Prozesse angeht. Für uns waren alle Prozesse jene die folgendermassen zu finden sin :

ps -edf | grep NAME

bringt dies was?
 
hmm, vielleicht haben wir noch nicht alles gesagt bekommen was ALLE Prozesse angeht. Für uns waren alle Prozesse jene die folgendermassen zu finden sin :

ps -edf | grep NAME

bringt dies was?

Naja, 'ps' reicht die an stdout weiter. Das heißt, du musst die dann dort abfangen, sonst landen die auf dem Bildschirm und nützen dir im Programm garnix mehr.
 
hmm...also ich bin jetzt eigendlich mit meinem Latein am Ende. Kannst du mir nicht einen Tipp geben wie ich das denn angehen kann? Möchte mir nicht gleich zu Anfang schlechte Noten einfangen...
 
Wie gesagt, ich schaus mir an, sobald ich die Zeit dafür hab. Die wächst bei mir leider auch nicht auf Bäumen. :-[
Werd mich bemühen, das fix hinzubekommen und zu erklären, sofern es nicht schon ein anderer tut. Aber ich hab auch nur 24h am Tag.
 
also bin jetzt schlauer geworden was die Erlaubnis Bash zu schreiben angeht :

was ich bis jetzt habe :

main(int argc, char** argv){

system(ps -edf|tr -s ' '>prozesse.txt);
system(while read linie; do pid=echo linie | cut -d ' ' -f2
prozs = echo linie | cut -d ' ' -f8
done<prozesse.txt);

in C müssen wir dann nur noch die geforderten Prozesse suchen und ein kill von der pid machen.

Die Parameter des Programmes : killall name_prozess nummer_signal. Das Signal ist in diesem Fall dann 9.

Ich denke dass das Kommando read(...) hilfreich ist. sowie das Kommando kill(9,pid).

Das einzige Problem das mir noch bleibt : wie kann ich die pid ausfindig machen? mit der Funktion read, nur wie? Wenn ich die hätte könnte ich ja das kill-Kommando geben und das Problem wäre gelost.

hilft das etwas weiter?
 
Zuletzt bearbeitet:
Hallo mal wieder,

bin jetzt mit meinem Programm schon sehr viel weiter.

Ich habe jetzt jeweils pids[ ] [ ] und cmds[ ] [ ] wo ich die Pids und die Prozessnamen drin habe. Mit Hilfe von strcmp soll ich den Prozess identifizieren.

Wie die Funktion strcmp wirkt ist mir schon bewusst, ich bin mir aber nicht recht im Klaren wie ich die auf die Pointers, sprich auf meine Tafeln anwenden soll...
 
PHP:
int pids[];
char* cmds[];

char* matchingName = ... ; // insert process name to be killed

// falls cmds am Ende einen Nullpointer enthält, dann etwa so
for (int i=0; cmds[i]; i++)
{
  if (0 == strcmp (cmds[i], matchingName))
  {
    kill (pids[i], 9);
  }
}
 
Zuletzt bearbeitet:
also ich habe das Programm jetzt fertig und auch soweit dass der compiler es annimmt, allerdings, wenn ich es ausführe mit ./mykillall knsole 9 passiert überhaupt nichts.
Der shell geht in die nächste Reihe und weiter passiert nichts.

Das Programm sieht wiefolgt aus :

int main(int argc, char** argv){

system("ps -edf|tr -s ' '>processus.txt");

int nbrespaces=0, nbr_lignes=0,pid;
int nbre_car=0;
int dscr;
char buf[1];
char** pids;
char** cmds;
int i;

dscr=fopen("processus.txt","w+");

while(read(dscr,buf[0],1)!=0) {

if (buf[0]=='\n') {nbr_lignes++;
nbre_car=0;
nbrespaces=0;}

else if (buf[0]==' ') {nbrespaces++;
nbre_car=0;}

else if (nbrespaces==1) {pids[nbr_lignes][nbre_car]=buf[0];
nbre_car++;}

else if (nbrespaces==7) {cmds[nbr_lignes][nbre_car]=buf[0]; /
nbre_car++;}
}

fclose("processus.txt");

for(i=0;i<=nbr_lignes;i++){
if (strcmp((*cmds),argv[1])==0) {pid=atoi(*pids);
kill(argv[2],pid);}
}

return 0;}

Weiss jemand wo jetzt noch immer der Fehler liegt? Wäre sehr nützlich, da das Programm benotet wird...

Danke schonmal im Voraus
 
Weiss jemand wo jetzt noch immer der Fehler liegt?
... na logisch:

dscr=fopen("processus.txt","w+");

Falls du das File mit "r" zum Lesen öffnest, sieht es schon mal besser aus.

Dann: Nichts gegen Latein, ich würde aber processus in processes umbenennen. ;)

So geht es besser: ;)
PHP:
char* matchingName = "...";
char buff [1024];

while (fgets (buff, sizeof (buff), dscr))
{
  char procName[256};

  // die nächste Zeile stimmt so noch nicht, sie würde für eine Formatierung
  // "<procName> <pid>" funktionieren
  if ( 2 == sscanf (buff, "%s %d", procName, &pid))
  {
    if ( 0 == strcmp (procName, matchingName))
    {
      kill (pid, 9);
    }
  }
}

Dann schon mal mit dem gdb anfreunden - man gdb
 
Danke.

Also ich habe den w+ durch ein r+ ausgetauscht und die Definition vom Buffer auch durch char buf[1024] ersetzt.

Ich habe allerdings nicht so ganz verstanden was du mit dem PHP-code sagen wolltest. Der Scan braucht ich (glaube ich) nicht , da dies schon im Argument ist. Die Funktion soll folgendermassen aufgerufen werden :

./mykillall konsole 9 ... eine weitere Interaktion soll nicht nötig sein.

hmm, und was ist gdb? habe hier leider kein Linux um ein man zu machen



P.S. : ich wusste gar nicht dass processus Latein ist;-). Das Programm schreibe ich nämlich auf französisch, daher der Name processus :-)
 
Zuletzt bearbeitet:
./mykillall konsole 9 ... eine weitere Interaktion soll nicht nötig sein.
OK, was ist die Aufgabe? Welche Prozesse sollen gekillt werden?

sscanf ist beim Parsen von strings nunmal unübertroffen, da bietet auch C++ nur Schlechteres. ;) Das Parsen der Zeilen in "processus.txt" ist aber schon nötig, oder?

Ohne Linux, nur so als Trockenschwimmen, ist Programmentwicklung allerdings kaum möglich.

Der gdb ist der Debugger.

man-pages sind auch im Internet abrufbar ;)
 
Also die genaue Aufgabenstellung lautet dass das Programm als Parameter den Namen eines Prozesses bekommt , sowie das ihm zu sendende Signal. Wir müssen also die PID's herausfinden und denen das angegebene Signal zusenden.

mykillall $1 $2 mit $1 den Prozessnamen und $2 das Signal.

Wie kann ich sscanf denn konkret anwenden? Wie gesagt, diese Funktion haben wir noch gar nicht gesehen. Alle Kommandos die wir bisweilen gesehen haben, sind schon im Programm verbaut.

Wo liegt denn eigendlich genau das Problem, dass das Programm nicht so funktioniert wie es soll?
 
Zurück
Oben Unten