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

最近刚好在学习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 $

试题--创建三个进程/线程,依次输出 A、B、C的更多相关文章

  1. 内核创建的用户进程printf不能输出一问的研究

    转:http://www.360doc.com/content/09/0315/10/26398_2812414.shtml 一:前言上个星期同事无意间说起,在用核中创建的用户空间进程中,使用prin ...

  2. python基础(16)-进程&线程&协程

    进程之multiprocessing模块 Process(进程) Process模块是一个创建进程的模块,借助这个模块,就可以完成进程的创建. 介绍 初始化参数 Process([group [, t ...

  3. 并发基础(三) java线程优先级

      在不同的JVM中(JVM也算是一个操作系统),有着不同的CPU调度算法,对于大部分的JVM来说,优先级也是调度算法中的一个参数.所以,线程优先级在一定程度上,对线程的调度执行顺序有所影响,但不能用 ...

  4. windows进程/线程创建过程 --- windows操作系统学习

    有了之前的对进程和线程对象的学习的铺垫后,我们现在可以开始学习windows下的进程创建过程了,我将尝试着从源代码的层次来分析在windows下创建一个进程都要涉及到哪些步骤,都要涉及到哪些数据结构. ...

  5. Python 多线程、多进程 (三)之 线程进程对比、多进程

    Python 多线程.多进程 (一)之 源码执行流程.GIL Python 多线程.多进程 (二)之 多线程.同步.通信 Python 多线程.多进程 (三)之 线程进程对比.多线程 一.多线程与多进 ...

  6. 菜鸡的Java笔记 第三十七 - java 线程与进程

    线程与进程        线程与进程的区别                最早的的时候DOS 系统有一个特点:只要电脑有病毒,那么电脑就死机了,是因为传统的DOS 系统属于单进程的操作系统       ...

  7. [OS] 操作系统-进程线程-经典面试笔试题

    题目转自:http://blog.csdn.net/morewindows/article/details/7392749 ·线程的基本概念.线程的基本状态及状态之间的关系? 线程,有时称为轻量级进程 ...

  8. 关于linux的一点好奇心(五):进程线程的创建

    一直以来,进程和线程的区别,这种问题一般会被面试官拿来考考面试者,可见这事就不太简单.简单说一点差异是,进程拥有独立的内存资源信息,而线程则共享父进程的资源信息.也就是说线程不拥有内存资源,所以对系统 ...

  9. 使用Java 多线程编程 让三个线程轮流输出ABC,循环10次后结束

    简要分析: 要求三个线程轮流输出,这里我们要使用一个对象锁,让关键部分的代码放入同步块当中.同时要有一个变量记录打印的次数到达10次循环后不再打印,另外一个就是要给每个线程一个标志号,我们根据标识号来 ...

随机推荐

  1. 5亿英镑!Imagination同意出售给私募机构Canyon Bridge

    集微网最新消息,据外媒 FT 报道,Imagination Technologies Group Plc(以下简称“Imagination”)同意由中国背景的私募基金Canyon Bridge Cap ...

  2. Html 空格与换行

    空格   换行 <br/>   调行距 <div style="line-height:10px"></div>

  3. JAVASCRIPT高程笔记-------第六章 面向对象的程序设计

    理解对象的概念  js中的对象与其他 编程语言中的类不一样  ECMAscript 没有类的概念      ECMA-262 把对象定义为 “无序属性的集合,其属性可以包含基本值,对象或者函数”   ...

  4. ASP FirstWeb

    //html <!DOCTYPE html> <html><head><meta http-equiv="Content-Type" co ...

  5. 文字滚屏控件(SliderPanel)

    http://www.delphifans.com/infoview/Article_629.html 日期:2005年9月6日 作者:arhaha {==================== 满天星 ...

  6. layui 或者layer 父页面获取子页面数据 或者子页面获取父页面操作方法

    var frameId = $(layero).find("iframe").attr('id');//父页面获取子页面的iframe var id = $(window.fram ...

  7. huawei 通过BGP的团体属性进行路由控制

    网络拓扑 XRV1的配置: =========================================================================== # sysname ...

  8. Win8Metro(C#)数字图像处理--2.30直方图均衡化

    原文:Win8Metro(C#)数字图像处理--2.30直方图均衡化 [函数名称] 直方图均衡化函数HistogramEqualProcess(WriteableBitmap src) [算法说明] ...

  9. C# dotnetcore2.0结合Selenium搜索网页

    using System; using OpenQA.Selenium; using OpenQA.Selenium.Chrome; namespace ConsoleApp_Selenium { c ...

  10. WPF判断两个PNG图片是否碰撞

    这个方法有几个前提 1.两个Image必须在一个Canvas中 2.两个Image的Canvas.Top和Canvas.Left必须赋值 上一篇讲了判断一个PNG图片某个点是否透明 这个基本类似的方法 ...