zoukankan      html  css  js  c++  java
  • 试题--创建三个进程/线程,依次输出 A、B、C

    这是一道机试题,大概的预期执行结果如下图所示

    最近刚好在学习linux编程,便使用多线程及多进程分别实现了一遍,其中多线程较为简单,使用0/1信号量在线程间实现生产者/消费者即可;多进程则稍微复杂一些,信号量必须设置为进程间通信,且存放在共享内存中,才能被多个进程访问。

    多线程的实现代码如下:

      1 /*================================================================
      2  *   Copyright (C) 2019 Ltd. All rights reserved.
      3  *
      4  *   File Name :fork_test.c
      5  *   Author    :Hamilton
      6  *   Date      :2019-06-05
      7  *   Descriptor:
      8  *
      9  ================================================================*/
     10 
     11 
     12 #include <sys/types.h>
     13 #include <sys/wait.h>
     14 #include <unistd.h>
     15 #include <unistd.h>
     16 #include <stdio.h>
     17 #include <stdlib.h>
     18 #include <semaphore.h>
     19 #include <sys/mman.h>
     20 #include <sys/stat.h>        /* For mode constants */
     21 #include <fcntl.h>           /* For O_* constants */
     22 #include <stdbool.h>
     23 #include<pthread.h>
     24 
     25 #define SHARED_MEM_NAME "/PRINTABC"
     26 
     27 struct shared_memory {
     28     sem_t sem[3];
     29 };
     30 
     31 const char ch[] = {'A', 'B', 'C'};
     32 int fd_shm = -1;
     33 bool finish = false;
     34 struct shared_memory *shared_mem_ptr = NULL;
     35 
     36 void err_check(int ret)
     37 {
     38     if (ret < 0)
     39     {
     40         perror("error: %d. 
    ");
     41         exit(ret);
     42     }
     43 }
     44 
     45 void err_exit(char *str)
     46 {
     47     perror(str);
     48     exit(1);
     49 }
     50 
     51 void* thread_handler(void* arg)
     52 {
     53     int index = *(char*)arg - 'A';
     54     int pre = index ? (index - 1) : 2;
     55 
     56     usleep(100000);
     57 
     58     while (!finish)
     59     {
     60         sem_wait(&shared_mem_ptr->sem[pre]);
     61         printf("%c 
    ", ch[index]);
     62         sem_post(&shared_mem_ptr->sem[index]);
     63         usleep(100000);
     64     }
     65     pthread_exit(NULL);
     66 }
     67 
     68 void sig_handler(int signo)
     69 {
     70     if (signo == SIGINT)
     71     {
     72         printf("received SIGINT
    ");
     73         finish = true;
     74     }
     75 }
     76 
     77 int main()
     78 {
     79     int err, i = 0;
     80 
     81     pthread_t tid[3];
     82 
     83     if (signal(SIGINT, sig_handler) == SIG_ERR)
     84         printf("
    can't catch SIGINT
    ");
     85 
     86     // Get shared memory
     87     if ((fd_shm = shm_open (SHARED_MEM_NAME, O_RDWR | O_CREAT, 0660)) < 0)
     88         err_exit ("shm_open");
     89 
     90     if (ftruncate (fd_shm, sizeof (struct shared_memory)) == -1)
     91         err_exit ("ftruncate");
     92 
     93     if ((shared_mem_ptr = mmap (NULL, sizeof (struct shared_memory), PROT_READ | PROT_WRITE, MAP_SHARED,
     94                     fd_shm, 0)) == MAP_FAILED)
     95         err_exit ("mmap");
     96 
     97     err_check(sem_init(&shared_mem_ptr->sem[0], 0, 0));
     98     err_check(sem_init(&shared_mem_ptr->sem[1], 0, 0));
     99     err_check(sem_init(&shared_mem_ptr->sem[2], 0, 1));
    100 
    101     while(i < 3)
    102     {
    103         err = pthread_create(&(tid[i]), NULL, &thread_handler, (void*)&ch[i]);
    104         if (err != 0)
    105             printf("
    can't create thread :[%s]", err);
    106         else
    107             printf("
     Thread created successfully
    ");
    108         i++;
    109     }
    110 
    111     for (i = 0; i < 3; i++)
    112     {
    113         pthread_join(tid[i], NULL);
    114         sem_destroy(&shared_mem_ptr->sem[i]);
    115     }
    116     shm_unlink(SHARED_MEM_NAME);
    117     printf("all threads have finished.
    ");
    118     return 0;
    119 }

     多进程的实现代码如下:

      1 /*================================================================
      2  *   Copyright (C) 2019 Ltd. All rights reserved.
      3  *
      4  *   File Name :fork_test.c
      5  *   Author    :Hamilton
      6  *   Date      :2019-06-05
      7  *   Descriptor:
      8  *
      9  ================================================================*/
     10 
     11 
     12 #include <sys/types.h>
     13 #include <sys/wait.h>
     14 #include <unistd.h>
     15 #include <unistd.h>
     16 #include <stdio.h>
     17 #include <stdlib.h>
     18 #include <semaphore.h>
     19 #include <sys/mman.h>
     20 #include <sys/stat.h>        /* For mode constants */
     21 #include <fcntl.h>           /* For O_* constants */
     22 #include <stdbool.h>
     23 
     24 #define SHARED_MEM_NAME "/PRINTABC"
     25 
     26 struct shared_memory {
     27     sem_t sem[3];
     28 };
     29 
     30 const char ch[] = {'A', 'B', 'C'};
     31 int fd_shm = -1;
     32 bool finish = false;
     33 struct shared_memory *shared_mem_ptr = NULL;
     34 
     35 void err_check(int ret)
     36 {
     37     if (ret < 0)
     38     {
     39         perror("error: %d. 
    ");
     40         exit(ret);
     41     }
     42 }
     43 
     44 void err_exit(char *str)
     45 {
     46     perror(str);
     47     exit(1);
     48 }
     49 
     50 void process_handler(int index)
     51 {
     52     int pre = index ? (index - 1) : 2;
     53 
     54     while (!finish)
     55     {
     56         sem_wait(&shared_mem_ptr->sem[pre]);
     57         printf("%c 
    ", ch[index]);
     58         sem_post(&shared_mem_ptr->sem[index]);
     59         usleep(100000);
     60     }
     61 }
     62 
     63 void sig_handler(int signo)
     64 {
     65     if (signo == SIGINT)
     66     {
     67         printf("received SIGINT
    ");
     68         finish = true;
     69     }
     70 }
     71 
     72 int main()
     73 {
     74     pid_t pid;
     75 
     76     if (signal(SIGINT, sig_handler) == SIG_ERR)
     77         printf("
    can't catch SIGINT
    ");
     78 
     79     // Get shared memory
     80     if ((fd_shm = shm_open (SHARED_MEM_NAME, O_RDWR | O_CREAT, 0660)) < 0)
     81         err_exit ("shm_open");
     82 
     83     if (ftruncate (fd_shm, sizeof (struct shared_memory)) == -1)
     84         err_exit ("ftruncate");
     85 
     86     if ((shared_mem_ptr = mmap (NULL, sizeof (struct shared_memory), PROT_READ | PROT_WRITE, MAP_SHARED,
     87                     fd_shm, 0)) == MAP_FAILED)
     88         err_exit ("mmap");
     89 
     90     err_check(sem_init(&shared_mem_ptr->sem[0], 1, 0));
     91     err_check(sem_init(&shared_mem_ptr->sem[1], 1, 0));
     92     err_check(sem_init(&shared_mem_ptr->sem[2], 1, 1));
     93 
     94     pid = fork();
     95 
     96     if (pid < 0)
     97     {
     98         printf("Fork error.
    
    ");
     99         exit(0);
    100     }
    101     else if (pid == 0)
    102     {
    103         printf("Process A, pid[%d]. 
    ", (int)getpid());
    104         usleep(10000);
    105         process_handler(0);
    106     }
    107     else
    108     {
    109         pid = fork();
    110 
    111         if (pid < 0)
    112         {
    113             printf("Fork error.
    
    ");
    114             exit(0);
    115         }
    116         else if (pid == 0)
    117         {
    118             printf("Process B, pid[%d]. 
    ", (int)getpid());
    119             process_handler(1);
    120         }
    121         else
    122         {
    123             printf("Process C, pid[%d]. 
    ", (int)getpid());
    124             process_handler(2);
    125             wait(NULL);
    126             sem_destroy(&shared_mem_ptr->sem[0]);
    127             sem_destroy(&shared_mem_ptr->sem[1]);
    128             sem_destroy(&shared_mem_ptr->sem[2]);
    129             shm_unlink(SHARED_MEM_NAME);
    130             printf("all processes have finished.
    ");
    131         }
    132     }
    133     return 0;
    134 }

    编译命令为:

    gcc threadabc.c -o threadabc -lpthread -lrt

    或者

      gcc forkabc.c -o forkabc -lpthread -lrt

    因使用到了多线程/进程,需连接 -lpthread;使用到了POSIX的信号量/共享内存相关,则需要连接 -lrt。关于linux多线程/多进程的开发及API接口的使用,可翻阅我近期摘抄的一些文章。

    运行结果:

    pi@raspberrypi:~/code/ipc/print_abc $ ./threadabc
    
     Thread created successfully
    
     Thread created successfully
    
     Thread created successfully
    A
    B
    C
    A
    B
    C
    A
    B
    C
    ^Creceived SIGINT
    all threads have finished.
    pi@raspberrypi:~/code/ipc/print_abc $ ./forkabc
    Process C, pid[7883].
    Process A, pid[7884].
    Process B, pid[7885].
    A
    B
    C
    A
    B
    C
    A
    B
    C
    A
    B
    C
    ^Creceived SIGINT
    received SIGINT
    received SIGINT
    all processes have finished.
    pi@raspberrypi:~/code/ipc/print_abc $
  • 相关阅读:
    单链表的实现C语言版
    顺序表的基本方法实现C语言版
    算法
    Redis
    Linux安装python3.6.1
    Markdown 基本使用手册
    设计Django个人博客网站
    RabbitMQ消息队列
    堡垒机 Paramiko 模块
    进程、线程、协程总结
  • 原文地址:https://www.cnblogs.com/miaoxiong/p/11158848.html
Copyright © 2011-2022 走看看