实验三 信号通信

【实验软硬件环境】

Linux、Win11、GCC

【实验目的与内容】

利用信号通信机制在父子进程几兄弟进程间进行通信。

父进程创建一个有名事件, 由子进程发送事件信号,父进程获取事 件信号后进行相应的处理

【实验程序及分析】

Windows下

父进程代码father.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <process.h>
#include <windows.h>
#include <stdio.h>

int main( ) {
STARTUPINFO sui; //启动信息结构体
PROCESS_INFORMATION pi; //在创建进程时相关的数据结构之一,该结构返回有关新进程及其主线程的信息。
ZeroMemory(&sui, sizeof(sui));
sui.cb = sizeof(STARTUPINFO);
CreateEvent(NULL, FALSE, FALSE, TEXT("event")); /*创建一个有名事件*/
if (!CreateProcess("child.exe", NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &sui, &pi)) { /*创建子进程*/
printf("create process failed\n");/*打印“创建子进程失败!”*/
return 0;/*退出*/
}
printf("Wait for event.\n");/*打印"Wait for event."*/
if (WAIT_FAILED == WaitForSingleObject(pi.hProcess, INFINITE)) { /*等待事件信号*/
printf("wait signal failed");/*打印“等待事件信号失败!”*/
return 0; /*退出*/
}
printf("Get the event");/*打印"Get the event"*/
return 0;
}
子进程代码child.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

int main() {
HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, TRUE, "event"); //打开命名事件
//OpenEvent是一个函数,可以用来执行返回事件对象的句柄
Sleep(1000);
printf("Signal the event to Parent?[Y\\N]:");
char ch;
scanf("%c", &ch);//接收字符
if (ch == 'Y') {
SetEvent(hEvent); //将事件置为有信号状态
} else {
return 0; //退出
}
Sleep(5000); //休眠一段时间
return 0;
}
代码分析
  1. 创建事件

    CreateEvent(NULL, FALSE, FALSE, TEXT("event")); /*创建一个有名事件*/

    1
    2
    3
    4
    5
    6
    7
    8
    9
    HANDLE CreateEvent(

    LPSECURITY_ATTRIBUTES lpEventAttributes, // SD

    BOOL bManualReset, // reset type

    BOOL bInitialState, // initial state

    LPCTSTR lpName // object name);

    参数说明:

    pEventAttributes:事件对象的安全属性,若设为NULL,则事件句柄不能被子进程继承。

    bManualReset:指定是创建一个手动事件对象还是创建一个自动事件对 象。设为TRUE时为手动事件对象,必须调用ResetEvent()函数将事件 重置为无信号状态。设为FALSE时为自动事件对象,系统将会在进程获得事件信号后自动将事件状态复位为无信号状态。

    lpName:用于指定事件名。若设为NULL时,则创建无名事件对象。

    返回值:如果创建事件对象成功,则返回事件对象的句柄;若失败,则返回NULL。

  2. 将一段内存块清零

    ZeroMemory(&sui, sizeof(sui));

    1
    2
    3
    4
    5
    VOID ZeroMemory( //将一段内存块清零

    PVOID Destination, // memory block

    SIZE_T Length // size of memory block);
  3. 关闭句柄

    1
    2
    3
    BOOL CloseHandle(

    HANDLE hObject // handle to object);
  4. 打开事件对象

    1
    2
    3
    4
    5
    6
    7
    HANDLE OpenEvent(

    DWORD dwDesiredAccess, // access

    BOOL bInheritHandle, // inheritance option

    LPCTSTR lpName // object name);

    参数说明:

    dwDesiredAccess:指定事件对象的访问权限。可取如下三个值的组合: EVENT_ALL_ACCESS,EVENT_MODIFY_STATE,SYNCHRONIZE。

    bInheritHandle:指定函数的返回句柄是否可被继承。

    lpName:要打开的事件对象的名称。

  5. 将事件置为有信号状态

    1
    2
    3
    BOOL SetEvent(

    HANDLE hEvent // handle to event);

【实验截图】

image-20220603154845600

image-20220603154905483

【实验心得体会】

掌握了进程之间的信号通信