【笔记】linux C编程

版权声明:欢迎评论交流,转载请注明原作者。 https://blog.csdn.net/m0_37809890/article/details/86198269

参考

https://www.cnblogs.com/zhanghongfeng/p/9108299.html
http://www.iteedu.com/os/linux/linuxprgm/linuxcfunctions/process/wait.php
https://blog.csdn.net/qq769651718/article/details/79393342

进程/信号 基础

  1. 信号:信号是一种软件中断,通过信号可以实现异步操作。Ctrl+c或delete都可以发送信号。

  2. 信号有若干种,接收到信号时有三种处理方式:忽略,默认,自定义函数。SIGKILL或SIGSTOP不能被忽略;大部分的信号默认操作都是终结进程。

  3. void (*signal(int sig, void (*handler)(int)))(int);接收一个信号;参数1是信号名,如SIGINT;参数2是处理方式,有三种: S I G _ I N G SIG\_ING , S I G _ D F L SIG\_DFL ,或一个带int参数(信号编号)、无返回值的函数。分别对应忽略,默认,自定义。
    在这里插入图片描述
    PS:第一次碰到真正需要解析的声明。。
    首先这是一个叫做 s i g n a l signal 的函数,它的参数类型和返回值类型都是神仙。
    先看参数,signal(int sig, void (*handler)(int)),第一个参数叫 s i g sig ,类型是 i n t int
    第二个参数叫 h a n d l e r handler ,按 B . 3 B.3 规则,它是一个指针;再按 B . 2 B.2 规则,它是一个指向函数的指针。这个函数的参数是一个 i n t int ,返回值是 v o i d void
    所以 s i g n a l signal 的参数分别是一个 i n t int 和一个函数指针,这是一个参数为 i n t int 返回值为 v o i d void 的函数。
    再看signal的返回值,void ( *signal )(int);
    B . 3 B.3 规则,它是一个指针,按 B . 2 B.2 规则,它是一个指向函数的指针,这个函数的参数是一个 i n t int ,返回值是 v o i d void
    所以, s i g n a l signal 函数接收一个 i n t int 参数和一个函数指针参数,返回值也是一个函数指针参数,指向的函数都是 v o i d f u n ( i n t ) void fun(int) 形式。
    查阅文档得, s i g n a l signal 函数会将传入的函数指针再作为返回值返回。我猜可能是为了级联。
    解析完成

  4. int kill(pid_t pid,int sig),可以传递任意信号(不只是终结)。参数sig代表信号编号,pid有几种情况:

    1. pid>0 将信号传给进程识别码为pid 的进程。
    2. pid=0 将信号传给和目前进程相同进程组的所有进程
    3. pid=-1 将信号广播传送给系统内所有的进程
    4. pid<0 将信号传给进程组识别码为pid绝对值的所有进程
  5. pid_t wait (int * status);暂停当前进程,直到收到信号或者子进程结束,子进程结束状态值会存储在status中,可以设为null。

  6. pause(),将进程挂起直到接收到一个信号

  7. pid_t fork(void); 创建子进程,完全复制父进程各项数据。父进程中返回子进程的pid,子进程返回0.

  8. unsigned int alarm(unsigned int seconds); 经过seconds秒数后向进程发送一个SIGALARM信号,如果未设置这个信号的处理,则终止进程。

测试代码

# include <unistd.h>
# include <sys/wait.h>
# include<bits/stdc++.h>
int son1_pid, son2_pid, my_name;
void parent_handler(int) 
{
	kill(son1_pid, 16);
    kill(son2_pid, 17);
    wait(nullptr);
    wait(nullptr);
    printf("Parent process is killed!!\n");
    exit(0);
}
void son_handler(int)
{
	printf("Child process %d is killed by parent !!\n",my_name );
	exit(0);
}
int create(int son_name, int sig_id)
{
    int pid = fork();
    if (pid == 0)
    {
    	my_name = son_name;
		signal(sig_id, son_handler);
        signal(SIGINT, SIG_IGN);
        while(1);
    }
    return pid;
}
int main()
{
	son1_pid = create(1, 16);
	son2_pid = create(2, 17);
	signal(SIGINT, parent_handler);
	while(1);
    return 0;
}

管道 基础

  1. ​管道是针对于本地计算机的两个进程之间的通信而设计的通信方法,管道建立后,实际上是获得两个文件描述符:一个用与读取而另一个用于写入。
  2. 任何从管道写入端写入的数据,可以从管道读取端读出。
  3. 管道是半双工的,数据只能向一个方向流动,需要双方通信时,要建立起两个管道。
  4. 管道存放在内存中,是一种独立的文件系统。
  5. int pipe(int filedes[2]);建立管道,filedes[0]为读端,filedes[1]为写端
  6. ssize_t write (int fd,const void * buf,size_t count);把buf所指的内存写入count个字节到文件fd中,返回0表示成功
  7. ssize_t read(int fd,void * buf ,size_t count);从fd所指的文件中读入count个字节到buf中,返回读入的字节数,最好将返回值与count比较

测试代码

#include <unistd.h>
#include <sys/wait.h>
#include <bits/stdc++.h>

void create(int son_name, int * pipedes)
{
    pipe(pipedes);
    int pid = fork();
    if (pid == 0)
    {
        char info[50]={};
        sprintf(info, "Child process %d is sending a message!", son_name);
        write(pipedes[1], info, 50);
        exit(0);
    }
}

int main()
{
    int pipedes1[2], pipedes2[2];
    char info1[50], info2[50];

    create(1, pipedes1);
    create(2, pipedes2);
    wait(nullptr); wait(nullptr);
    read(pipedes1[0], info1, 50);
    printf("%s\n", info1);
    read(pipedes2[0], info2, 50);
    printf("%s\n", info2);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37809890/article/details/86198269