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

最近刚好在学习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. .NET Core 中使用 Humanizer 显示友好时间格式

    今天在将一个 .net framework 项目迁移至 .net core 的过程中,在迁移到显示友好时间格式(比如“1分钟前”,“1小时前”)的代码时,找了找看有没有对应的开源库,结果找到了 Hum ...

  2. python 识别身份证号码

    # !/usr/bin/python # -*-coding:utf-8-*- import sys import time time1 = time.time() from PIL import I ...

  3. 【Git】生成Patch和使用Patch

    1.生成Patch(俗称快照) 先来看看repo manifest 的用法 <1>cd /工作目录/项目目录/.repo/manifests <2>repo manifest ...

  4. 赵伟国:陆资无法进入台湾紫光要到WTO控告(芯片是为了经济安全,高通找的人不是很聪明)

    集微网消息,昨天由全球半导体联盟和上海市集成电路行业协会联合举办的Memory +论坛在上海举行,会议透过来自存储器.逻辑和系统市场领先企业的高管,深入他们对未来存储器的应用.可行的商业模式,以及逻辑 ...

  5. stdlib.h,string.h,wchar.h的函数列表(cplusplus.com就有,很清楚)goodx

    Multibyte characters mblen Get length of multibyte character (function ) mbtowc Convert multibyte se ...

  6. 快速开发平台 WebBuilder 8 发布

    快速开发平台  WebBuilder 8 发布 了解:http://www.putdb.com,官网:http://www.geejing.com 什么是WebBuilder? WebBuilder是 ...

  7. windows 下 php 实现在线预览附件(pdf)

    (写的有点啰嗦,具体的实现方法只是粗体和代码就够了) 给市场部门用dede做个cms,需要附件在线查看.公司有个系统(就叫develop_cms吧)是已经实现的,本以为很容易,不过是下一个插件然后把附 ...

  8. Codility---PermCheck

    Task description A non-empty zero-indexed array A consisting of N integers is given. A permutation i ...

  9. javascript 实现ajax

    AJAX 英文名称 Asynchronous JavaScript and XML即异步的 JavaScript 和 XML AJAX 是与服务器交换数据并更新部分网页一门无刷新技术构建自己的ajax ...

  10. PHP网站开发方案

    一. 开发成员 a)项目主管 b)页面美工c)页面开发 d)服务端程序开发e)系统与数据管理f)测试与版本控制 二. 网站组开发简明流程 三. 开发工具与环境 a) 服务器配置i. WEB服务器: F ...