试题--创建三个进程/线程,依次输出 A、B、C
2024-09-01 01:20:51
这是一道机试题,大概的预期执行结果如下图所示
最近刚好在学习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 $
最新文章
- Dubbo项目demo搭建
- c语言内存原理
- Ubuntu 安装Theano
- What is “:-!!” in C code?
- string find
- 更改RAC日志组
- bodyParser注意“需要请求头的支持”
- 一个经典例子让你彻彻底底理解java回调机制
- Android中用双缓存技术,加载网络图片
- 如何搭建maya plugin develop environment on MAC OS X
- armeabi,armeabi-v7a ,x86 和mips 都是什么?
- Android之NDK编程(JNI)
- POJ 3233 Matrix Power Serie
- tomcat错误信息解决方案 严重:StandardServer.await:
- EF调用sp,EF自动生成返回类型
- CentOS配置
- 【问题解决方案】AttributeError: module &#39;pygal&#39; has no attribute &#39;Worldmap&#39;
- union的特性,去重与不去重
- Real-time chart using ASP.NET Core and WebSocket
- 9-9-B+树-查找-第9章-《数据结构》课本源码-严蔚敏吴伟民版
热门文章
- #748 – 获得按下时对应位置点的大小(Getting the Size of a Contact Point during Raw Touch)
- WPF中Polyline拐角的bug
- otrs离线部署
- Oracle 已有则更新,没有则插入
- 专门用于消息回调窗口的窗口标识HWND_MESSAGE(创建一个非可视、没有z-order的窗口)
- Linux参数调优
- Qt程序发行Linux版,软件打包知识(patchelf 工具修改依赖库,确认 qmake -v 是自己使用的Qt版本,否则用export PATH进行修改)good
- Android零基础入门第52节:自定义酷炫进度条
- 进程交互还可以使用QSharedMemory
- Qt移动开发大部分的场景基本上实现没问题,listview支持刷新3000~5000的实时数据没有任何压力(QML的几个大型应用)