-1

如何解决以下实现信号量同步的问题...

出于这个问题的目的,我们将对交叉路口进行建模,如上所示,将其划分为四分之一,并确定每个四分之一车道通过该部分进入交叉路口。(澄清一下:我们在道路的右侧行驶。)转弯表示通过交叉路口的一个、两个或三个部分的进展(为简单起见,假设在交叉路口不发生 U 形转弯) . 因此,如果一辆车从北方接近,根据它的去向,它会按如下方式通过十字路口:

        | ! + ^ |                   
        | ! + ! |
        | v + ! |
 --------------------------
   <----|NW + NE|  <----
        |   +   |
 ++++++++++++++++++++++++++                 
        |   +   |
  ----> |SW + SE| ---->
 --------------------------
        | ! + ^ |
        | ! + ! |
        | v + ! |



Right: NW
Straight: NW-SW
Left: NW-SW-SE 

谁先到达路口,谁先行。

没有两辆车可以同时在交叉路口的同一部分。不要彼此通过相同的方式。如果两辆车从同一个方向接近并朝同一个方向行驶,那么最先到达交叉路口的汽车应该是最先到达目的地的汽车。同样,汽车不应该在十字路口相互“跳跃”。例如,假设一辆车进入十字路口并直行。然后另一辆车从同一方向进入交叉路口并向左行驶。第二辆车应该在第一辆车之后离开路口。然而,假设一辆车进入交叉路口并且向左行驶。如果另一辆车从同一方向进入交叉路口并向右行驶,那么它可能会更早离开交叉路口,因为第一辆车,即使它领先于第二辆车,可能还不能左转。每辆车在接近交叉口(接近)时应打印一条消息,进入交叉口的一个或多个区域((区域1),区域2和区域3),离开交叉口(离开),指示车号,接近方向和目的地方向。

从给定方向接近交叉路口的汽车应以相同的顺序进入交叉路口。请注意,在汽车接近交叉路口以减速之前不应进行同步。换句话说,不要在进入交叉路口的区域1之前简单地打印接近,例如,两个事件之间应该有一个同步原语。没有其他订购要求。例如,对于从不同方向接近的汽车,没有订购要求。我应该允许两辆或更多辆汽车同时进入十字路口,而不允许来自任何方向的交通使来自任何其他方向的交通饿死。

createcars 创建 20 辆汽车并将它们传递到接近交叉路口,为每辆汽车分配一个随机方向。我需要为他们分配一个随机的转弯方向;我也可以在接近交叉路口执行此操作。

其他例程 gostraight、turnright 和 turnleft 可能有助于或可能不会有助于实施此解决方案。我可以使用它们或丢弃它们。

这是一辆车(8 号车)从东方到达并朝西方行驶的示例输出。请注意,区域(例如,区域 1)是相对于每辆汽车定义的。向右行驶的汽车将输出 region1。直线行驶的汽车将输出 region1 和 region2。向左行驶的汽车将输出 region1、region2 和 region3。

approaching: car =  8, direction = E, destination = W
region1:     car =  8, direction = E, destination = W
region2:     car =  8, direction = E, destination = W
leaving:     car =  8, direction = E, destination = W

以下是我的例程..

    #include <types.h>
    #include <lib.h>
    #include <test.h>
    #include <thread.h>



    /*
    * Number of cars created.
    */

    #define NCARS 20


    /*
    *
    * Function Definitions
    *
    */

    static const char *directions[] = { "N", "E", "S", "W" };

    static const char *msgs[] = {
        "approaching:",
        "region1:    ",
        "region2:    ",
        "region3:    ",
        "leaving:    "
    };

    /* use these constants for the first parameter of message */
    enum { APPROACHING, REGION1, REGION2, REGION3, LEAVING };

    static void
    message(int msg_nr, int carnumber, int cardirection, int destdirection)
    {
        kprintf("%s car = %2d, direction = %s, destination = %s\n",
                msgs[msg_nr], carnumber,
                directions[cardirection], directions[destdirection]);
    }

    /*
    * gostraight()
    *
    * Arguments:
    *      unsigned long cardirection: the direction from which the car
    *              approaches the intersection.
    *      unsigned long carnumber: the car id number for printing purposes.
    *
    * Returns:
    *      nothing.
    *
    * Notes:
    *      This function should implement passing straight through the
    *      intersection from any direction.
    *      Write and comment this function.
    */

    static void gostraight(unsigned long cardirection, unsigned long carnumber)
    {
        /*
         * Avoid unused variable warnings.
         */

        (void) cardirection;
        (void) carnumber;
    }


    /*
    * turnleft()
    *
    * Arguments:
    *      unsigned long cardirection: the direction from which the car
    *              approaches the intersection.
    *      unsigned long carnumber: the car id number for printing purposes.
    *
    * Returns:
    *      nothing.
    *
    * Notes:
    *      This function should implement making a left turn through the 
    *      intersection from any direction.
    *      Write and comment this function.
    */

    static void turnleft(unsigned long cardirection, unsigned long carnumber)
    {
        /*
         * Avoid unused variable warnings.
         */

        (void) cardirection;
        (void) carnumber;
    }


    /*
    * turnright()
    *
    * Arguments:
    *      unsigned long cardirection: the direction from which the car
    *              approaches the intersection.
    *      unsigned long carnumber: the car id number for printing purposes.
    *
    * Returns:
    *      nothing.
    *
    * Notes:
    *      This function should implement making a right turn through the 
    *      intersection from any direction.
    *      Write and comment this function.
    */

    static void turnright(unsigned long cardirection, unsigned long carnumber)
    {
        /*
         * Avoid unused variable warnings.
         */

        (void) cardirection;
        (void) carnumber;
    }


    /*
    * approachintersection()
    *
    * Arguments: 
    *      void * unusedpointer: currently unused.
    *      unsigned long carnumber: holds car id number.
    *
    * Returns:
    *      nothing.
    *
    * Notes:
    *      I need to change this function to implement sempahore synchronization. These
    *      threads are created by createcars().  Each one must choose a direction
    *      randomly, approach the intersection, choose a turn randomly, and then
    *      complete that turn.  The code to choose a direction randomly is
    *      provided, the rest is left to you to implement.  Making a turn
    *      or going straight should be done by calling one of the functions
    *      above.
    */

    static void approachintersection(void * unusedpointer, unsigned long carnumber)
    {
        int cardirection;

        /*
         * Avoid unused variable and function warnings.
         */

        (void) unusedpointer;
        (void) carnumber;
    (void) gostraight;
    (void) turnleft;
    (void) turnright;

        /*
         * cardirection is set randomly.
         */

        cardirection = random() % 4;
    }


    /*
    * createcars()
    *
    * Arguments:
    *      int nargs: unused.
    *      char ** args: unused.
    *
    * Returns:
    *      0 on success.
    *
    * Notes:
    *       Driver code to start up the approachintersection() threads.
    *      I can modify this code as well for my solution..
    */

    int createcars(int nargs, char ** args)
    {
        int index, error;

        /*
         * Avoid unused variable warnings.
         */

        (void) nargs;
        (void) args;

        /*
         * Start NCARS approachintersection() threads.
         */

        for (index = 0; index < NCARS; index++) {

                error = thread_fork("approachintersection thread",
                                    NULL,
                                    index,
                                    approachintersection,
                                    NULL
                                    );

                /*
                 * panic() on error.
                 */

                if (error) {

                        panic("approachintersection: thread_fork failed: %s\n",
                              strerror(error)
                              );
                }
        }

        return 0;
    }

  [1]: http://i.stack.imgur.com/1389H.gif
4

1 回答 1

0

考虑到您的十字路口只有四个区域可供汽车占用,您需要四个信号量和四个线程来解决您的问题。让我们将所有到达路口的汽车放入单个 FIFO 队列中,而不管汽车前进的方向。这将确保汽车按到达顺序通过过境点。然后每个线程从队列中挑选一辆汽车,确定一条路径并等待路径中的第一个信号量。在获取信号量后,它会检查这是否是路径中的最后一个区域,然后在汽车到达交叉口的目的地边界时释放一个信号量。否则,线程将在其路径中的下一个信号量上挂起。在获取下一个信号量后,它会释放先前占用区域的信号量。

几个笔记。这种方法甚至适用于 U 形转弯。当我们在十字路口有 4 辆车并且每辆车都在等待下一个区域空闲时,就像在现实生活中一样,“交通堵塞”是可能的。您可以通过将线程数限制为三个来避免卡纸

于 2012-10-11T17:55:32.263 回答