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

最近刚好在学习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. Lua学习 2) —— Android与Lua互调

    2014-07-09 一.Android类调用lua并回调 Android调用Lua函数,同一时候把类作为參数传递过去.然后再Lua中回调类的函数 调用lua mLuaState = LuaState ...

  2. C类型和存储方式的语言变量

    变量的作用域:有效射程变量 >局部变量 1.在函数中的局部变量,量在该函数结束后自己主动撤销 2.函数内的复合语句中的局部变量(比方for语句),这个变量在复合语句结束后自己主动撤销.这个变量能 ...

  3. 操作系统hosts文件

    为了便于北京和大连两个更好的测试系统.该公司专门申请一个域名:大连r \\ u0026 D侧只需要部署(我方系统全权负责在大连研发.所以在大连并列比较的部署方面easy--不要忘记,该项目比我们实际做 ...

  4. CentOS6.5优盘安装

    从CentOS6.5开始直接把iso文件写入u盘就可实现优盘安装 windows平台:1.用UltraISO打开iso(如:CentOS-6.5-x86_64-bin-DVD1.iso)2.然后点“启 ...

  5. Halcon程序导出运行的方法

    1 在Halcon中打开程序,如clip.hdev: 2 文件->导出 设置使用导出模板,使用UTF-8编码: 3 导出cs文件 4 新建Winform程序 5 在工具栏中点右键->选择项 ...

  6. 【Linux】samba服务

    samba是一个实现不同操作系统之间文件共享和打印机共享的一种SMB协议的免费软件. ①Samba软件包的安装 使用源安装,在终端中输入如下命令: #sudo apt-get install samb ...

  7. wpf自定义带刻度的柱状图控件

    效果图: 主要代码xaml: <UserControl x:Class="INSControls._01Conning.Steer.ConningSpeedBar" xmln ...

  8. iText类库再pdf中显示中文字体

    using iTextSharp.text; using System; using System.Collections.Generic; using System.IO; using System ...

  9. 领域驱动设计(DDD)的实践经验分享之持久化透明

    原文:领域驱动设计(DDD)的实践经验分享之持久化透明 前一篇文章中,我谈到了领域驱动设计中,关于ORM工具该如何使用的问题.谈了很多我心里的想法,大家也对我的观点做了一些回复,或多或少让我深深感觉到 ...

  10. DLL里面socket(Delphi的代码)

    http://hi.baidu.com/game_base/item/f617e4136414148889a956ed   本文简单介绍了当前Windows支持的各种Socket I/O模型,如果你发 ...