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

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

多线程的实现代码如下:

 /*================================================================
* Copyright (C) 2019 Ltd. All rights reserved.
*
* File Name :fork_test.c
* Author :Hamilton
* Date :2019-06-05
* Descriptor:
*
================================================================*/ #include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
#include <stdbool.h>
#include<pthread.h> #define SHARED_MEM_NAME "/PRINTABC" struct shared_memory {
sem_t sem[];
}; const char ch[] = {'A', 'B', 'C'};
int fd_shm = -;
bool finish = false;
struct shared_memory *shared_mem_ptr = NULL; void err_check(int ret)
{
if (ret < )
{
perror("error: %d. \n");
exit(ret);
}
} void err_exit(char *str)
{
perror(str);
exit();
} void* thread_handler(void* arg)
{
int index = *(char*)arg - 'A';
int pre = index ? (index - ) : ; usleep(); while (!finish)
{
sem_wait(&shared_mem_ptr->sem[pre]);
printf("%c \n", ch[index]);
sem_post(&shared_mem_ptr->sem[index]);
usleep();
}
pthread_exit(NULL);
} void sig_handler(int signo)
{
if (signo == SIGINT)
{
printf("received SIGINT\n");
finish = true;
}
} int main()
{
int err, i = ; pthread_t tid[]; if (signal(SIGINT, sig_handler) == SIG_ERR)
printf("\ncan't catch SIGINT\n"); // Get shared memory
if ((fd_shm = shm_open (SHARED_MEM_NAME, O_RDWR | O_CREAT, )) < )
err_exit ("shm_open"); if (ftruncate (fd_shm, sizeof (struct shared_memory)) == -)
err_exit ("ftruncate"); if ((shared_mem_ptr = mmap (NULL, sizeof (struct shared_memory), PROT_READ | PROT_WRITE, MAP_SHARED,
fd_shm, )) == MAP_FAILED)
err_exit ("mmap"); err_check(sem_init(&shared_mem_ptr->sem[], , ));
err_check(sem_init(&shared_mem_ptr->sem[], , ));
err_check(sem_init(&shared_mem_ptr->sem[], , )); while(i < )
{
err = pthread_create(&(tid[i]), NULL, &thread_handler, (void*)&ch[i]);
if (err != )
printf("\ncan't create thread :[%s]", err);
else
printf("\n Thread created successfully\n");
i++;
} for (i = ; i < ; i++)
{
pthread_join(tid[i], NULL);
sem_destroy(&shared_mem_ptr->sem[i]);
}
shm_unlink(SHARED_MEM_NAME);
printf("all threads have finished.\n");
return ;
}

多进程的实现代码如下:

 /*================================================================
* Copyright (C) 2019 Ltd. All rights reserved.
*
* File Name :fork_test.c
* Author :Hamilton
* Date :2019-06-05
* Descriptor:
*
================================================================*/ #include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
#include <stdbool.h> #define SHARED_MEM_NAME "/PRINTABC" struct shared_memory {
sem_t sem[];
}; const char ch[] = {'A', 'B', 'C'};
int fd_shm = -;
bool finish = false;
struct shared_memory *shared_mem_ptr = NULL; void err_check(int ret)
{
if (ret < )
{
perror("error: %d. \n");
exit(ret);
}
} void err_exit(char *str)
{
perror(str);
exit();
} void process_handler(int index)
{
int pre = index ? (index - ) : ; while (!finish)
{
sem_wait(&shared_mem_ptr->sem[pre]);
printf("%c \n", ch[index]);
sem_post(&shared_mem_ptr->sem[index]);
usleep();
}
} void sig_handler(int signo)
{
if (signo == SIGINT)
{
printf("received SIGINT\n");
finish = true;
}
} int main()
{
pid_t pid; if (signal(SIGINT, sig_handler) == SIG_ERR)
printf("\ncan't catch SIGINT\n"); // Get shared memory
if ((fd_shm = shm_open (SHARED_MEM_NAME, O_RDWR | O_CREAT, )) < )
err_exit ("shm_open"); if (ftruncate (fd_shm, sizeof (struct shared_memory)) == -)
err_exit ("ftruncate"); if ((shared_mem_ptr = mmap (NULL, sizeof (struct shared_memory), PROT_READ | PROT_WRITE, MAP_SHARED,
fd_shm, )) == MAP_FAILED)
err_exit ("mmap"); err_check(sem_init(&shared_mem_ptr->sem[], , ));
err_check(sem_init(&shared_mem_ptr->sem[], , ));
err_check(sem_init(&shared_mem_ptr->sem[], , )); pid = fork(); if (pid < )
{
printf("Fork error.\n\n");
exit();
}
else if (pid == )
{
printf("Process A, pid[%d]. \n", (int)getpid());
usleep();
process_handler();
}
else
{
pid = fork(); if (pid < )
{
printf("Fork error.\n\n");
exit();
}
else if (pid == )
{
printf("Process B, pid[%d]. \n", (int)getpid());
process_handler();
}
else
{
printf("Process C, pid[%d]. \n", (int)getpid());
process_handler();
wait(NULL);
sem_destroy(&shared_mem_ptr->sem[]);
sem_destroy(&shared_mem_ptr->sem[]);
sem_destroy(&shared_mem_ptr->sem[]);
shm_unlink(SHARED_MEM_NAME);
printf("all processes have finished.\n");
}
}
return ;
}

编译命令为:

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[].
Process A, pid[].
Process B, pid[].
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 $

最新文章

  1. Dubbo项目demo搭建
  2. c语言内存原理
  3. Ubuntu 安装Theano
  4. What is “:-!!” in C code?
  5. string find
  6. 更改RAC日志组
  7. bodyParser注意“需要请求头的支持”
  8. 一个经典例子让你彻彻底底理解java回调机制
  9. Android中用双缓存技术,加载网络图片
  10. 如何搭建maya plugin develop environment on MAC OS X
  11. armeabi,armeabi-v7a ,x86 和mips 都是什么?
  12. Android之NDK编程(JNI)
  13. POJ 3233 Matrix Power Serie
  14. tomcat错误信息解决方案 严重:StandardServer.await:
  15. EF调用sp,EF自动生成返回类型
  16. CentOS配置
  17. 【问题解决方案】AttributeError: module &#39;pygal&#39; has no attribute &#39;Worldmap&#39;
  18. union的特性,去重与不去重
  19. Real-time chart using ASP.NET Core and WebSocket
  20. 9-9-B+树-查找-第9章-《数据结构》课本源码-严蔚敏吴伟民版

热门文章

  1. #748 – 获得按下时对应位置点的大小(Getting the Size of a Contact Point during Raw Touch)
  2. WPF中Polyline拐角的bug
  3. otrs离线部署
  4. Oracle 已有则更新,没有则插入
  5. 专门用于消息回调窗口的窗口标识HWND_MESSAGE(创建一个非可视、没有z-order的窗口)
  6. Linux参数调优
  7. Qt程序发行Linux版,软件打包知识(patchelf 工具修改依赖库,确认 qmake -v 是自己使用的Qt版本,否则用export PATH进行修改)good
  8. Android零基础入门第52节:自定义酷炫进度条
  9. 进程交互还可以使用QSharedMemory
  10. Qt移动开发大部分的场景基本上实现没问题,listview支持刷新3000~5000的实时数据没有任何压力(QML的几个大型应用)