Многопоточность против многопроцессорности в C

#c #multithreading #multiprocessing #fork

#c #многопоточность #многопроцессорная обработка #форк

Вопрос:

Я пытаюсь изучить многопроцессорность и то, как она работает по сравнению с многопоточностью. Мне трудно найти хороший источник его использования, и мне было интересно, может ли кто-нибудь привести мне несколько примеров по сравнению с многопоточностью.

Для практики я решил попробовать написать код с потоками, а затем с процессами. Я застрял на том, чтобы выяснить, как создавать процессы, которые я хочу, закрывать процессы и использовать мьютекс для блокировки / разблокировки процесса.

Например, если я хочу создать 5 потоков в функции, я могу сделать это:

 for(i = 0; i < 5; i  ) {
    pthread_create(amp;(myThread[i]), NULL, myFunction, argument); 
}
 

Как бы я это сделал в процессе? Я рассматривал возможность вызова функции, а затем вызова fork в функции, но я не уверен, как получить конкретное число. Например, если бы я сделал это:

 myFunction(argument) {
    fork();
    fork();
    fork();
    ...
}
 

Это дало бы мне всего 8 процессов. Слишком много. Но если бы я удалил fork() , у меня было бы всего 4 процесса, что слишком мало. Как мне создать ровно столько процессов, сколько я хочу?

Далее, если бы я должен был закрыть потоки, я бы просто сделал это:

 for(i = 0; i < 5; i  ){
    pthread_join(myThread[i],NULL);
}
 

Но как бы я это сделал для процессов?

Наконец, для обеспечения безопасности потоков я могу использовать мьютекс и разблокировать блокировку вызова, когда это необходимо.

 static pthread_mutex_t my_mutex;
pthread_mutex_lock(amp;my_mutex);
...
pthread_mutex_unlock(amp;my_mutex);
 

Могу ли я использовать мьютексы с процессом? Если нет, то какая альтернатива есть? Если да, то как будет отличаться его реализация?

Ответ №1:

Вы должны проверять возвращаемое значение при вызове fork . Например:

 for (int i = 0; i < 4;   i)
{
  pid_t child = fork();
  if(pid == -1) perror("wtf? "), abort(); // failed!
  if(!pid) {
    // in child process ...:
    do_work();
    exit(0);
  }
}
 

-1 Возвращаемое значение указывает на ошибку, в то время 0 как указывает, что вы находитесь внутри дочернего процесса.

Если вы находитесь в дочернем процессе, либо разорвите цикл, либо продолжайте выполнять некоторую работу перед выходом из процесса.

Обратите внимание, что нет необходимости в управлении мьютексами, поскольку родительский процесс и дочерние процессы не используют одну и ту же память. Это также означает, что им нужно будет взаимодействовать другими способами (часто с использованием каналов, сокетов unix или специально выделенной общей памяти).

Комментарии:

1. Но если родители и дочерние элементы читают и записывают в один и тот же файл в коде, наверняка это потребует некоторой защиты, не так ли?

2. Файлы имеют блокировки ОС при записи в них, но да , вам определенно нужно учитывать эти проблемы. Многопоточность отличается от многопоточности, и у каждого есть свои преимущества и недостатки.

3. @Tarface если несколько процессов используют один и тот же файл, они могут координировать свои действия с помощью блокировки файла с помощью fcntl() или flock() .

4. @Tarface — если вы нашли ответ полезным, не стесняйтесь поддержать или принять ответ.

5. @Tarface, пожалуйста, обратите внимание : обычно это небезопасно для fork многопоточного процесса . Например, другие потоки могут находиться в критической секции (т. Е. Внутри вызова malloc or printf ), оставляя дочерний процесс в плохой ситуации.

Ответ №2:

Как мне создать ровно столько процессов, сколько я хочу?

Используйте exec семейство API.

Но как бы я это сделал для процессов?

wait заблокирует текущий процесс до завершения дочернего процесса.