有名管道,signal

有名管道

1. 创建有名管道

  • 函数原型: int mkfifo(const char *pathname, mode_t mode);

  • 描述: 该函数用于创建一个有名管道(FIFO)。pathname 是你想要创建的管道的路径,mode 是设置管道权限的标志(如读写权限)。成功时返回 0,失败时返回 -1 并设置 errno

2. 打开有名管道

  • 函数原型: int open(const char *pathname, int flags);

  • 描述: 该函数用于打开有名管道。pathname 是有名管道的路径,flags 指定打开文件的模式(如只读、只写、读写等)。成功时返回文件描述符,失败时返回 -1 并设置 errno

3. 读数据

  • 函数原型: ssize_t read(int fd, void *buf, size_t count);

  • 描述: 该函数从有名管道中读取数据。fd 是文件描述符,buf 是用来存储读取数据的缓冲区,count 是要读取的字节数。成功时返回实际读取的字节数,失败时返回 -1 并设置 errno。如果有名管道的另一端已关闭,返回 0 表示到达文件末尾。

4. 写数据

  • 函数原型: ssize_t write(int fd, const void *buf, size_t count);

  • 描述: 该函数向有名管道写入数据。fd 是文件描述符,buf 是包含要写入数据的缓冲区,count 是要写入的字节数。成功时返回实际写入的字节数,失败时返回 -1 并设置 errno

5. 关闭有名管道

  • 函数原型: int close(int fd);

  • 描述: 该函数用于关闭文件描述符。fd 是要关闭的文件描述符。成功时返回 0,失败时返回 -1 并设置 errno

6. 删除有名管道

  • 函数原型: int unlink(const char *pathname);

  • 描述: 该函数用于删除有名管道文件。pathname 是要删除的有名管道的路径。成功时返回 0,失败时返回 -1 并设置 errno

有名管道的主要特点:

1. 持久性

  • 有名管道在文件系统中存在,直到被明确删除。与匿名管道不同,有名管道的存在不依赖于进程的生命周期,因此它们可以在不同的进程和会话之间共享。

2. 全双工通信

  • 虽然单个有名管道是半双工的(即数据只能单向流动),但可以通过创建两个有名管道实现全双工通信:一个用于发送数据,另一个用于接收数据。

3. 进程间通信

  • 有名管道允许不同进程间的通信,而不仅限于父子进程。任何可以访问有名管道的进程都可以进行读写操作,从而实现进程间的数据交换。

4. 阻塞特性

  • 读操作阻塞: 如果管道中没有数据,读取操作会阻塞,直到有数据可读。
  • 写操作阻塞: 如果管道的读端没有被打开,写入操作会阻塞,直到有读端打开以读取数据。

5. 数据流

  • 数据在有名管道中的流动是按顺序的,写入的数据会按照写入的顺序被读取。

6. 同步和互斥

  • 由于有名管道的阻塞特性,它本身提供了一种简单的同步机制。例如,读操作的阻塞可以确保数据被写入后再进行读取。

7. 权限和安全

  • 有名管道的权限可以通过 chmod 命令设置,允许用户控制哪些进程可以访问管道。这提供了一定的安全控制,但需注意管道的权限设置以防止未授权访问。

8. 文件系统接口

  • 有名管道在文件系统中以特殊文件的形式存在,允许使用标准的文件操作命令(如 ls, cat, rm 等)进行管理。这使得有名管道在文件系统中易于识别和操作。

9. 跨会话和跨用户

  • 由于有名管道存在于文件系统中,它们可以被不同用户和不同会话的进程访问,只要它们有适当的权限。

10. 非适合长时间存储

  • 有名管道主要用于短期的数据传输,不适合存储长时间的数据。数据在有名管道中的生命周期通常与进程的通信需求相关。

signal

 

1. signal()

  • 函数原型: void (*signal(int signum, void (*handler)(int)))(int);

  • 描述: 设置信号的处理程序。signum 是要处理的信号的编号,handler 是信号处理函数的指针。返回值是旧的信号处理函数的指针。

  • 用法: 用于设置特定信号的处理函数。当指定的信号发生时,操作系统会调用设定的处理函数。

2. sigaction()

  • 函数原型: int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

  • 描述: 用于更复杂的信号处理设置。signum 是信号的编号,act 是一个 sigaction 结构体的指针,用于指定新的信号处理行为,oldact 是一个指向 sigaction 结构体的指针,用于保存旧的信号处理行为。

  • 用法: 允许设置信号处理程序以及附加选项,如信号阻塞或修改信号处理的标志。

3. sigemptyset()

  • 函数原型: int sigemptyset(sigset_t *set);

  • 描述: 初始化信号集为空。set 是指向 sigset_t 类型的信号集的指针。

  • 用法: 用于创建一个不包含任何信号的空信号集。这在设置信号屏蔽字或处理信号时非常有用。

4. sigaddset()

  • 函数原型: int sigaddset(sigset_t *set, int signum);

  • 描述: 将指定的信号添加到信号集中。set 是信号集,signum 是要添加的信号的编号。

  • 用法: 用于将信号添加到信号集中。

5. sigdelset()

  • 函数原型: int sigdelset(sigset_t *set, int signum);

  • 描述: 从信号集中删除指定的信号。set 是信号集,signum 是要删除的信号的编号。

  • 用法: 用于从信号集中移除某个信号。

6. sigismember()

  • 函数原型: int sigismember(const sigset_t *set, int signum);

  • 描述: 检查信号是否在信号集中。set 是信号集,signum 是要检查的信号的编号。返回值为非零表示信号在集合中,零表示不在集合中。

  • 用法: 用于判断信号是否属于指定的信号集。

7. sigprocmask()

  • 函数原型: int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

  • 描述: 改变进程的信号屏蔽字。how 指定如何修改当前信号屏蔽字(如 SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK),set 是新的信号集,oldset 用来保存之前的信号集。

  • 用法: 用于阻塞、解除阻塞或设置进程的信号屏蔽字。

8. kill()

  • 函数原型: int kill(pid_t pid, int sig);

  • 描述: 向指定进程发送信号。pid 是进程的 ID,sig 是要发送的信号的编号。

  • 用法: 用于向进程发送信号,例如终止进程或通知进程某个事件发生

信号类型 

  • SIGHUP (1): 挂起信号

    • 描述: 通常表示终端的挂起,或者控制终端的连接断开。通常用于重新加载配置文件。
  • SIGINT (2): 中断信号

    • 描述: 通常由用户通过按 Ctrl+C 发送,用于中断当前进程。
  • SIGQUIT (3): 退出信号

    • 描述: 通常由用户通过按 Ctrl+\ 发送,导致进程终止并生成核心转储(core dump)。
  • SIGILL (4): 非法指令信号

    • 描述: 进程尝试执行非法的处理器指令。
  • SIGTRAP (5): 跟踪陷阱信号

    • 描述: 用于调试目的,例如断点。
  • SIGABRT (6): 异常终止信号

    • 描述: 由 abort() 函数发送,通常表示进程因内部错误而终止。
  • SIGBUS (7): 总线错误信号

    • 描述: 进程尝试访问无效地址或进行非法内存访问。
  • SIGFPE (8): 浮点异常信号

    • 描述: 进程进行浮点运算时发生错误(如除零错误)。
  • SIGKILL (9): 强制终止信号

    • 描述: 强制终止进程,不能被捕获、阻塞或忽略。
  • SIGUSR1 (10): 用户定义信号1

    • 描述: 用户可以自定义使用的信号。
  • SIGSEGV (11): 段错误信号

    • 描述: 进程试图访问无效的内存段。
  • SIGUSR2 (12): 用户定义信号2

    • 描述: 用户可以自定义使用的信号。
  • SIGPIPE (13): 管道破裂信号

    • 描述: 进程向一个已经关闭的管道写数据时发送。
  • SIGALRM (14): 定时器到期信号

    • 描述: 由 alarm() 函数设置的定时器到期时发送。
  • SIGTERM (15): 终止信号

    • 描述: 请求进程终止,进程可以捕获并进行清理操作。
  • SIGSTKFLT (16): 堆栈故障信号

    • 描述: 发生堆栈溢出时发送。
  • SIGCHLD (17): 子进程状态改变信号

    • 描述: 子进程状态发生变化时发送给父进程。
  • SIGCONT (18): 继续执行信号

    • 描述: 恢复被停止的进程的执行。
  • SIGSTOP (19): 停止信号

    • 描述: 停止进程执行,不能被捕获、阻塞或忽略。
  • SIGTSTP (20): 终端停止信号

    • 描述: 通常由用户通过按 Ctrl+Z 发送,暂停当前进程的执行。
  • SIGTTIN (21): 终端输入信号

    • 描述: 进程在后台尝试读取终端时发送。
  • SIGTTOU (22): 终端输出信号

    • 描述: 进程在后台尝试写入终端时发送。
  • SIGURG (23): 紧急数据到达信号

    • 描述: 通知进程有紧急数据到达。
  • SIGXCPU (24): CPU 时间限制超标信号

    • 描述: 进程使用的 CPU 时间超出设定限制。
  • SIGXFSZ (25): 文件大小限制超标信号

    • 描述: 进程尝试写入超过文件大小限制的文件时发送。
  • SIGVTALRM (26): 虚拟定时器到期信号

    • 描述: 虚拟计时器到期时发送。
  • SIGPROF (27): 统计定时器到期信号

    • 描述: 统计定时器到期时发送。
  • SIGWINCH (28): 窗口大小改变信号

    • 描述: 终端窗口大小改变时发送。
  • SIGIO (29): I/O 操作信号

    • 描述: I/O 操作完成时发送。
  • SIGPWR (30): 电源恢复信号

    • 描述: 电源恢复时发送。
  • SIGSYS (31): 不合法系统调用信号

    • 描述: 进程执行非法的系统调用时发送

设置信号处理函数

可以使用 signal()sigaction() 函数设置信号处理函数。

#include 
#include 

void signal_handler(int signal) {
    printf("Received signal %d\n", signal);
}

int main() {
    signal(SIGINT, signal_handler);  // 设置信号处理函数
    while (1) {
        // 主循环
    }
    return 0;
}

 使用 sigaction() 设置信号处理函数

#include 
#include 

void signal_handler(int signal) {
    printf("Received signal %d\n", signal);
}

int main() {
    struct sigaction sa;
    sa.sa_handler = signal_handler;
    sa.sa_flags = 0;  // 默认值
    sigemptyset(&sa.sa_mask);  // 不屏蔽任何信号

    sigaction(SIGINT, &sa, NULL);  // 设置信号处理函数
    while (1) {
        // 主循环
    }
    return 0;
}

你可能感兴趣的:(算法,开发语言,linux,数据结构,c语言)