pthread и рекурсивный вызов execvp в C - PullRequest
1 голос
/ 12 ноября 2011

Для начала извините за мой английский:)

Я искал способ создания потока каждый раз, когда моя программа находит каталог, чтобы вызвать саму программу, но с новым аргументом argv [2] (который является текущим каталогом). Я сделал это успешно с fork (), но с pthread у меня есть некоторые трудности. Я не знаю, смогу ли я сделать что-то подобное:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <dirent.h>


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

    pthread_t  threadID[10] = {0};
    DIR * dir;
    struct dirent * entry;
    struct stat status;
    pthread_attr_t attr;
pthread_attr_init(&attr);

int i = 0;
char *res;
char *tmp; 
char *file;

 if(argc != 3)
{
    printf("Usage : %s <file> <dir>\n", argv[0]);
    exit(EXIT_FAILURE);
}


 if(stat(argv[2],&status) == 0)
 {
    dir = opendir(argv[2]);
    file = argv[1];
 }
 else
    exit(EXIT_FAILURE);

while ((entry = readdir(dir))) 
{

  if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
{

  tmp = malloc(strlen(argv[2]) + strlen(entry->d_name) + 2);

  strcpy(tmp, argv[2]);
  strcat(tmp, "/");
      strcat(tmp, entry->d_name);
  stat(tmp, &status);

  if (S_ISDIR(status.st_mode))
  {     

    argv[2] = tmp; 
    pthread_create( &threadID[i], &attr, execvp(argv[0], argv), NULL);

    printf("New thread created : %d", i);
    i++;

   }
   else if (!strcmp(entry->d_name, file))
   {
        printf(" %s was found - Thread number = %d\n",tmp, i);
        break;
    }

    free(tmp);
}  



}

pthread_join( threadID[i] , &res );

exit(EXIT_SUCCESS);


}

На самом деле это не работает: pthread_create (& threadID [i], & attr, execvp (argv [0], argv), NULL);

У меня нет ошибки времени выполнения, но когда файл для поиска находится в другом каталоге, поток не создается, и поэтому execvp (argv [0], argv) не вызывается ...

Спасибо за помощь,

Simon

Ответы [ 2 ]

6 голосов
/ 12 ноября 2011

Вызов execvp из нового потока бессмысленен - ​​все функции в семействе exec уничтожат все потоки в текущем процессе и заменят все это процессом, который вы exec извлекаете.

Если вы хотите порождать дочерний процесс, вам все равно нужно использовать традиционную комбинацию fork() / exec(). Обратите внимание, что дочерний процесс, который вы отключаете, обычно имеет только один поток (тот, который называется fork()), поэтому вам не нужно слишком беспокоиться о том, что делают другие ваши потоки.

3 голосов
/ 12 ноября 2011

Во-первых, это не может работать .

Подумайте об этом: execve системный вызов заменяет текущий процесс (и все потоки в нем)новый процесс.Если вы успешно создали первый поток, ваш основной поток мгновенно испарится, как только первый поток достигнет execve.

Во-вторых, pthread_create требует указатель функции в качестве третьего параметра.Но вместо этого вы передаете это выражение: execvp(argv[0], argv).Что делает это выражение (при оценке)?

Он заменяет ваш текущий процесс новым!

Вы должны построить свой код с -Wall и исправить все предупреждения.

Создание вашего кода в таком виде приводит к:

gcc -c t.c -Wall
t.c: In function ‘main’:
t.c:18: warning: implicit declaration of function ‘pthread_attr_init’
t.c:55: warning: implicit declaration of function ‘pthread_create’
t.c:70: warning: implicit declaration of function ‘pthread_join’

Это легко исправить, просто добавьте пропущенный #include <pthread.h>.После этого компилятор сообщит вам, что у вас проблема:

gcc -c t.c -Wall
t.c: In function ‘main’:
t.c:56: warning: passing argument 3 of ‘pthread_create’ makes pointer from integer without a cast
/usr/include/pthread.h:227: note: expected ‘void * (*)(void *)’ but argument is of type ‘int’
t.c:71: warning: passing argument 2 of ‘pthread_join’ from incompatible pointer type
/usr/include/pthread.h:244: note: expected ‘void **’ but argument is of type ‘char **’
...