c - 创建线程并将它们加入 for 循环

c - creating threads & joining them in a for loop

所以基本上我正在用 c 为车辆进出小区 phone 塔区制作一个模拟器。我正在尝试在 simulator.c 中添加代码,使该函数为每个手机信号塔生成一个新线程以及一个线程来处理显示。模拟器程序应该继续运行,直到所有 7 个手机信号塔线程都完成,并且手机信号塔线程应该继续运行,直到它们收到关闭请求。显示线程无限期运行,但在模拟器进程完成时被终止。我无法理解应该使用哪些参数来创建和加入线程。我 post 编辑了我目前在 simulator.c 程序中的内容。我的尝试是尝试循环语句以为 7 个基站创建 7 个线程。我不确定 pthread_create 的第一个参数是否正确,我也不确定我的第 4 个参数应该是什么。我知道我应该提出某种论点,但我不确定是什么。此外,我不太确定 "the cell tower threads should continue until they receive a shutdown request." 的要求意味着什么 每个手机信号塔线程应该从 cellTower.c 调用 handleIncomingRequests() 并且显示线程应该从 display.c[ 调用 showSimulation() =14=]

任何帮助将不胜感激。我在网上看了一些关于 c 线程的视频,但我对它们的工作方式仍然有点困惑。我 post 在我认为只与这个问题相关的文件下方编辑,但如果有人要我 post 整个程序的每个文件,我不介意。

simulator.c:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "simulator.h"

#include "display.c"
#include "cellTower.c"

int main() {
  City     ottawa;

  // Cell tower data
  short    xLocations[7] = {100, 400, 650, 640, 400, 120, 200};
  short    yLocations[7] = {100, 200, 150, 450, 500, 350, 500};
  short     cellRadii[7] = {110, 200, 150, 180, 160, 120, 100};
  int      cellColors[7] = {0xFF8822 /*Orange*/, 0xFF2222 /*Red*/, 0xFFFF44 /*Yellow*/,
                0x22FF22 /*Green*/, 0xAA66FF /*Purple*/, 0x0099FF /*Blue*/,
                0x999999 /*LightGray*/};

  // Set up the Cell Towers with the above data ... and no connected vehicles to begin
  ottawa.numTowers = 7;
  for (int i=0; i<ottawa.numTowers; i++) {
    ottawa.towers[i].online = 1;
    ottawa.towers[i].id = (unsigned char)i;
    ottawa.towers[i].x = xLocations[i];
    ottawa.towers[i].y = yLocations[i];
    ottawa.towers[i].radius = cellRadii[i];
    ottawa.towers[i].color = cellColors[i];
    ottawa.towers[i].numConnectedVehicles = 0;
    for (int j=0; j<MAX_CONNECTIONS; j++)
      ottawa.towers[i].connectedVehicles[j].connected = 0;
  }

  // Remove the line of code below.  Add code to spawn the necessary threads and
  // wait for their completion before exiting gracefully with some kind of message
    pthread_t cellTowers[ottawa.numTowers];
    int i;
    for(i = 0; i < ottawa.numTowers; i++){
        pthread_create(cellTowers[i], NULL, handleIncomingRequests, "");
        pthread_join(cellTowers[i], NULL);
    }

    pthread_t displayTower;
    pthread_create(&displayTower, NULL, showSimulation, "");



}

simulator.h:

#define VEHICLE_SPEED           3   // Forward pixels per movement
#define VEHICLE_TURN_ANGLE      5   // degrees to turn for each vehicle movement

#define NUM_TOWERS              7   // Number of cell towers within the city borders

#define SERVER_IP     "127.0.0.1"   // IP address of simulator server
#define SERVER_PORT          6000   // PORT of the simulator server

// Command codes sent from client to server
#define SHUTDOWN           1
#define CONNECT            2
#define UPDATE             3

// Command codes sent from server to client
#define YES                5
#define NO                 6
#define NOT_OK_BOUNDARY    7
#define NOT_OK_COLLIDE     8


typedef struct {
  int   x;
  int   y;
  int   direction;
  char  towerID;
} Vehicle;

typedef struct {
  int   x;
  int   y;
  char  connected;
} ConnectedVehicle;


typedef struct {
  char               online; // 0 = no, 1 = yes
  char               id;
  short              x;
  short              y;
  short              radius;
  int                color;
  ConnectedVehicle   connectedVehicles[MAX_CONNECTIONS];
  short              numConnectedVehicles;
} CellTower;

typedef struct {
  CellTower towers[NUM_TOWERS];
  short     numTowers;
} City;

cellTower.c:

#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>


void *handleIncomingRequests(void *ct) {
  CellTower       *tower = ct;
}

display.c:

#include <unistd.h>
#include <X11/Xlib.h>

//Display-related variables
Display *display;
Window   win;
GC       gc;


// Initialize and open the simulator window with size CITY_WIDTH x CITY_HEIGHT.
void initializeWindow() {
  // Open connection to X server
  display = XOpenDisplay(NULL);

  // Create a simple window, set the title and get the graphics context then
  // make is visible and get ready to draw
  win = XCreateSimpleWindow(display,  RootWindow(display, 0), 0, 0,
                CITY_WIDTH, CITY_HEIGHT, 0, 0x000000, 0xFFFFFF);
  XStoreName(display, win, "Vehicle Simulator");
  gc = XCreateGC(display, win, 0, NULL);
  XMapWindow(display, win);
  XFlush(display);
  usleep(20000);  // sleep for 20 milliseconds.
}

// Close the display window
void closeWindow() {
  XFreeGC(display, gc);
  XUnmapWindow(display, win);
  XDestroyWindow(display, win);
  XCloseDisplay(display);
}


// Redraw all the cell towers and all the vehicles that are connected to towers.
// This code should run in an infinite loop continuously drawing the city.
// Vehicles are drawn as circles with radius VEHICLE_RADIUS.
void *showSimulation(void *c) {
  City  *city = c;

  // Open the window
  initializeWindow();

  // Now keep redrawing until someone kills the thread
  while(1) {
    // Erase the background 
    XSetForeground(display, gc, 0xFFFFFF);
    XFillRectangle(display, win, gc, 0, 0, CITY_WIDTH, CITY_HEIGHT);

    // Draw all the cell towers
    for (int i=0; i<city->numTowers; i++) {
      short r = city->towers[i].radius;
      XSetForeground(display, gc, city->towers[i].color);
      for (int b=-3;b<=3; b++)
    XDrawArc(display, win, gc,
         city->towers[i].x-r+b, city->towers[i].y-r+b,
         2*(r-b), 2*(r-b), 0, 360*64);
    }

    // Draw all the vehicles within each cell tower's range 
    for (int t=0; t<city->numTowers; t++) {
      for (int i=0; i<MAX_CONNECTIONS; i++) {
    if (city->towers[t].connectedVehicles[i].connected) {
      XSetForeground(display, gc, city->towers[t].color);
      XFillArc(display, win, gc,
           city->towers[t].connectedVehicles[i].x-VEHICLE_RADIUS,
           city->towers[t].connectedVehicles[i].y-VEHICLE_RADIUS,
           2*VEHICLE_RADIUS, 2*VEHICLE_RADIUS, 0, 360*64);
      XSetForeground(display, gc, 0x000000); // draw a black border
      XDrawArc(display, win, gc,
           city->towers[t].connectedVehicles[i].x-VEHICLE_RADIUS,
           city->towers[t].connectedVehicles[i].y-VEHICLE_RADIUS,
           2*VEHICLE_RADIUS, 2*VEHICLE_RADIUS, 0, 360*64);
    }
      }
    }
    XFlush(display);
    usleep(2000);
  }

  closeWindow();
  pthread_exit(NULL);
}

此外,如果有人有一些有用的线程资源,那也将不胜感激!!!

这里有几个问题:

pthread_t cellTowers[ottawa.numTowers];
int i;
for(i = 0; i < ottawa.numTowers; i++){
    pthread_create(cellTowers[i], NULL, handleIncomingRequests, "");
    pthread_join(cellTowers[i], NULL);
}
  1. pthread_create 存储它在指向的内存位置创建的线程ID第一个参数。 因此,第一个参数应该是 &cellTowers[i](或等同于 cellTowers + i),并且 而不是 cellTowers[i] 您传递的是

    您的编译器应该警告您,您正在传递错误类型的值。如果您还没有打开编译器警告,请现在打开。对于 GCC,使用 -Wall -Wextra -Werror.

  2. 每当您观察到这个序列时:

    pthread_create ...
    pthread_join ...

    两者的thread-id相同,你可以立即知道程序坏了。 pthread_join 等待 线程完成。因此,在第一个线程退出之前不会创建其他线程。

    大多数线程程序的工作方式:

    for (...) pthread_create... // create all worker threads
    // possibly perform additional work in main thread
    for (...) pthread_join... // wait for all threads to finish

  3. 最后,进入你的问题:第 4 个参数应该是什么?

    因为 handleIncomingRequests() 期望参数是指向 CellTower 的指针,这就是第四个参数应该是什么(该参数直接 传递 给你的功能)。

    在此程序中,第 4 个参数应为 &ottawa.towers[i](或等价于 ottawa.towers + i)。