Основная проблема объясняется в моем комментарии:
Вы не передаете действительный указатель на функцию потока. В большинстве случаев вы почти сошли с рук от неправильного использования этого в вызове printf()
в robotAct()
; вам категорически не сходит с рук при вызове Learning()
, где вы разыменовываете недействительный не указатель.
Решение заключается в создании массива целых чисел в основной программе, который содержит идентификационные номера роботов (int id[N];
). Затем инициализируйте каждый элемент и передайте &id[i]
в pthread_create()
.
Не следует печатать адреса в формате %d
(даже если он работает в 32-разрядных системах; он не работает в 64-разрядных системах). Правильный метод - использовать %p
для форматирования адреса. Или, в этом случае, выведите целое число, а не адрес, используя *robot_id
.
Следующий код имеет минимальную адаптацию к исходному коду и не был скомпилирован или протестирован (могут быть проблемы за пределами измененных строк):
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#define N 5
#define M 3
#define LEFT (robot_id - 1) % N
#define RIGHT (robot_id + 1) % N
pthread_t robots_id[N];
sem_t simulations[M];
pthread_mutex_t sever_mutex;
void Learning(int robot_id)
{
printf("learning robot = %d\n", robot_id);
}
void *robotAct(void *id)
{
int *robot_id = id;
printf("robot id = %d\n", *robot_id); // Changed
Learning(*robot_id);
return 0; // Added
}
int main(int argc, char *argv[])
{
int E, T;
int id[N]; // Added
E = atoi(argv[1]);
T = atoi(argv[2]);
printf("Initializing Robot!\n");
//Initializes the simulations
for (int i = 0; i < M; i++)
{
sem_init(&simulations[i], 0, 0);
}
//Initializes the robots
for (int i = 0; i < N; i++)
{
printf("Robot %d is created\n", i + 1);
id[i] = i + 1; // Added
pthread_create(&robots_id[i], NULL, robotAct, &id[i]); // Changed
}
sleep(T);
printf("Terminating Robots\n");
for (int i = 0; i < N; i++)
{
pthread_cancel(robots_id[i]);
}
printf("Termination is completed!\n");
printf("-------Report-------------\n");
//getReport();
return 0;
}
Избегайте использования pthread_cancel()
для завершения потоков; потоки должны заканчиваться под контролем. Например, в главном потоке может быть установлен флаг, указывающий, что потоки должны прекратиться, и они будут периодически это проверять. Обычно pthread_join()
используется для очистки завершенных потоков.
Для будущих публикаций, пожалуйста, прочитайте о том, как создать MCVE ( Минимальный, Полный, Проверяемый Пример ). Приведенные части кода не имеют отношения к проблеме - мьютекс и семафоры, например, на самом деле не используются.