网站抠图怎么做的,wordpress用户站内信,wordpress编辑主页,建筑工程证书查询目录
一、无名管道
二、有名管道
三、共享内存
四、信号量
五、消息队列
六、套接字 一、无名管道 1.只能用于具有亲缘关系的进程之间的通信(也就是父子进程或者兄弟进程)。 2.是一个单工的通信模式#xff0c;具有固定的读端和写端。 3.管道也可以看成是一种特殊的文件…目录
一、无名管道
二、有名管道
三、共享内存
四、信号量
五、消息队列
六、套接字 一、无名管道 1.只能用于具有亲缘关系的进程之间的通信(也就是父子进程或者兄弟进程)。 2.是一个单工的通信模式具有固定的读端和写端。 3.管道也可以看成是一种特殊的文件对于它的读写也可以使用普通的read()、write()等函数。但是它不属于任何文件系统并且只存在于内存中。 #include unistd.h
int pipe(int filedes[2]);
在管道中文件描述符数组的第一个元素索引为0用于读取第二个元素索引为1用于写入。
#include stdio.h
#include stdlib.h
#include unistd.h#define BUFFER_SIZE 25
#define READ_END 0
#define WRITE_END 1int main()
{char write_msg[BUFFER_SIZE] Hello, child!;char read_msg[BUFFER_SIZE];int fd[2];pid_t pid;// 创建管道if (pipe(fd) -1) {fprintf(stderr, Pipe failed);return 1;}// 创建子进程pid fork();if (pid 0) {fprintf(stderr, Fork failed);return 1;}// 父进程if (pid 0) {// 关闭写入端因为父进程不会写入close(fd[WRITE_END]);// 从管道中读取消息read(fd[READ_END], read_msg, BUFFER_SIZE);printf(Parent received message from child: %s\n, read_msg);// 关闭读取端close(fd[READ_END]);} // 子进程else { // 关闭读取端因为子进程不会读取close(fd[READ_END]);// 写入消息到管道write(fd[WRITE_END], write_msg, BUFFER_SIZE);// 关闭写入端close(fd[WRITE_END]);}return 0;
}./a.out 执行结果Parent received message from child: Hello, child! 二、有名管道 mkfifo(const char *pathname, mode_t mode): 这个函数用于创建一个有名管道。参数pathname是要创建的管道的路径名mode是指定管道权限的位掩码。返回值成功时返回0失败时返回-1并设置errno变量表示错误类型。 open(const char *pathname, int flags, mode_t mode): 这个函数用于打开文件或管道。参数pathname是要打开的文件或管道的路径名flags指定打开文件的方式如只读、只写、读写等mode是当创建新文件时指定的权限。返回值成功时返回文件描述符失败时返回-1并设置errno变量表示错误类型。 write(int fd, const void *buf, size_t count): 这个函数用于向文件描述符指定的文件或管道中写入数据。参数fd是打开文件或管道时返回的文件描述符buf是要写入的数据缓冲区count是要写入的字节数。返回值成功时返回实际写入的字节数失败时返回-1并设置errno变量表示错误类型。 read(int fd, void *buf, size_t count): 这个函数用于从文件描述符指定的文件或管道中读取数据。参数fd是打开文件或管道时返回的文件描述符buf是用于接收数据的缓冲区count是要读取的最大字节数。返回值成功时返回实际读取的字节数失败时返回-1并设置errno变量表示错误类型。 close(int fd): 这个函数用于关闭打开的文件描述符。参数fd是要关闭的文件描述符。返回值成功时返回0失败时返回-1并设置errno变量表示错误类型。 unlink(const char *pathname): 这个函数用于删除文件或链接。参数pathname是要删除的文件或链接的路径名。返回值成功时返回0失败时返回-1并设置errno变量表示错误类型。 #include stdio.h
#include stdlib.h
#include unistd.h
#include fcntl.h
#include sys/types.h
#include sys/stat.h#define BUFFER_SIZE 25int main()
{char *fifo_name ./name;char write_msg[BUFFER_SIZE] Hello, world!;char read_msg[BUFFER_SIZE];// 创建有名管道mkfifo(fifo_name, 0666);pid_t pid fork();if (pid 0)// 子进程负责写入{// 打开管道进行写入int fd_write open(fifo_name, O_WRONLY);write(fd_write, write_msg, BUFFER_SIZE);close(fd_write);} else if (pid 0) // 父进程负责读取{ // 打开管道进行读取int fd_read open(fifo_name, O_RDONLY);read(fd_read, read_msg, BUFFER_SIZE);printf(Received message: %s\n, read_msg);close(fd_read);} else // fork失败{fprintf(stderr, Fork failed);return 1;}// 删除管道unlink(fifo_name);return 0;
}三、共享内存
共享内存是最高效的因为避免了数据在用户空间和内核空间的来回拷贝 ftok(const char *pathname, int proj_id): ftok()函数用于生成一个唯一的key用于创建或访问共享内存。参数pathname是一个路径名proj_id是一个整数用于生成key。返回值如果成功返回一个唯一的key如果失败返回-1。 shmget(key_t key, size_t size, int shmflg): shmget()函数用于创建共享内存段或获取共享内存段的标识符。参数key是由ftok()生成的唯一keysize是共享内存的大小shmflg是标志位用于指定权限和行为。返回值如果成功返回共享内存段的标识符如果失败返回-1。 shmat(int shmid, const void *shmaddr, int shmflg): shmat()函数用于将共享内存连接到当前进程的地址空间。参数shmid是共享内存段的标识符shmaddr通常为NULL表示系统自动选择地址shmflg是标志位通常为0。返回值如果成功返回指向共享内存段的指针如果失败返回(void *)-1。 shmdt(const void *shmaddr): shmdt()函数用于将共享内存从当前进程的地址空间分离。参数shmaddr是指向共享内存段的指针。返回值如果成功返回0如果失败返回-1。 shmctl(int shmid, int cmd, struct shmid_ds *buf): shmctl()函数用于对共享内存进行控制操作如删除共享内存段。参数shmid是共享内存段的标识符cmd是控制命令buf是一个指向shmid_ds结构体的指针用于获取共享内存的状态信息。返回值如果成功返回0如果失败返回-1。 读端
#include stdio.h
#include stdlib.h
#include unistd.h
#include sys/ipc.h
#include sys/shm.h
#include string.h#define SHM_SIZE 1024int main()
{key_t key ftok(/, R); // 生成共享内存的key// 创建共享内存段int shmid shmget(key, SHM_SIZE, IPC_CREAT | 0666);if (shmid -1) {perror(shmget);exit(1);}// 将共享内存连接到当前进程的地址空间char *shmaddr shmat(shmid, NULL, 0);if (shmaddr (void *)-1) {perror(shmat);exit(1);}// 写入数据到共享内存strcpy(shmaddr, Hello, shared memory!);// 分离共享内存if (shmdt(shmaddr) -1) {perror(shmdt);exit(1);}printf(数据已写入共享内存\n);return 0;
}写端
#include stdio.h
#include stdlib.h
#include unistd.h
#include sys/ipc.h
#include sys/shm.h#define SHM_SIZE 1024int main()
{key_t key ftok(/, R); // 生成共享内存的key// 获取共享内存段int shmid shmget(key, SHM_SIZE, 0666);if (shmid -1) {perror(shmget);exit(1);}// 将共享内存连接到当前进程的地址空间char *shmaddr shmat(shmid, NULL, 0);if (shmaddr (void *)-1){perror(shmat);exit(1);}printf(从共享内存中读取到的消息%s\n, shmaddr);// 分离共享内存if (shmdt(shmaddr) -1) {perror(shmdt);exit(1);}return 0;
}写端执行后 数据已写入共享内存 读端执行后 从共享内存中读取到的消息Hello, shared memory! 四、信号量 1.信号量实现互斥
#include stdio.h
#include stdlib.h
#include unistd.h
#include sys/types.h
#include sys/ipc.h
#include sys/sem.h#define KEY 1234 // 信号量的键值// 定义一个联合体用于semctl初始化
union semun {int val;struct semid_ds *buf;unsigned short *array;
};// 创建一个二值信号量并初始化为1
int create_semaphore()
{// 创建一个信号量集包含1个信号量int semid semget(KEY, 1, IPC_CREAT | 0666); if (semid -1) {perror(semget);exit(1);
}union semun arg;arg.val 1; // 初始值为1表示资源可用if (semctl(semid, 0, SETVAL, arg) -1) // 初始化信号量{perror(semctl);exit(1);}return semid;
}// P操作等待资源
void P(int semid)
{struct sembuf op;op.sem_num 0; // 信号量集中的第一个信号量op.sem_op -1; // 对信号量执行P操作op.sem_flg 0;if (semop(semid, op, 1) -1) {perror(semop);exit(1);}
}// V操作释放资源
void V(int semid)
{struct sembuf op;op.sem_num 0; // 信号量集中的第一个信号量op.sem_op 1; // 对信号量执行V操作op.sem_flg 0;if (semop(semid, op, 1) -1) {perror(semop);exit(1);}
}int main()
{int semid create_semaphore(); // 创建信号量pid_t pid fork(); // 创建子进程if (pid -1) {perror(fork);exit(1);}if (pid 0) // 子进程{P(semid); // 等待资源printf(Child process: Counter decremented by 1.\n);V(semid); // 释放资源} else // 父进程{sleep(1); // 让子进程有机会先运行P(semid); // 等待资源printf(Parent process: Counter incremented by 1.\n);V(semid); // 释放资源}return 0;
}semget(key_t key, int nsems, int semflg) 这个函数用于创建一个新的信号量集或获取一个现有信号量集的标识符。key是一个用于唯一标识信号量集的键值。nsems指定了信号量集中的信号量数量。semflg是一组标志用于指定创建信号量集的权限和行为。返回值成功时返回信号量集的标识符失败时返回-1。 semctl(int semid, int semnum, int cmd, union semun arg) 这个函数用于对信号量集进行控制操作如初始化、设置值、获取值等。semid是信号量集的标识符。semnum是指定的信号量在集合中的索引通常为0。cmd是指定要执行的控制命令。arg是一个联合体用于传递控制命令的参数。返回值根据控制命令不同而不同。 semop(int semid, struct sembuf *sops, size_t nsops) 这个函数用于执行一组信号量操作如等待资源P操作和释放资源V操作。semid是信号量集的标识符。sops是一个指向信号量操作结构体数组的指针。nsops是指定的信号量操作结构体数组的大小。返回值成功时返回0失败时返回-1。 struct sembuf 这是一个结构体用于描述信号量操作。它包含了三个字段 sem_num信号量集中的信号量索引。sem_op信号量操作通常是-1P操作等待资源或1V操作释放资源。sem_flg信号量操作的标志位通常为0。 union semun 这是一个联合体用于传递给semctl()函数的参数。它包含了多个字段其中的一个字段可以根据不同的控制命令来使用比如用于设置或获取信号量值时使用的val字段用于获取信号量状态信息时使用的buf字段等 create_semaphore(): 这个函数用于创建一个二值信号量并将其初始化为1。首先它调用 semget() 函数创建一个包含一个信号量的信号量集如果创建失败则会打印错误信息并退出程序。然后它使用 semctl() 函数将信号量的值初始化为1表示资源可用。最后它返回创建的信号量集的标识符。 P(int semid): 这个函数用于执行 P 操作即等待资源。首先它定义了一个 struct sembuf 结构体 op用于描述信号量操作。然后它将 op.sem_num 设置为0表示信号量集中的第一个信号量。接着它将 op.sem_op 设置为-1表示对信号量执行 P 操作。最后它调用 semop() 函数执行信号量操作如果操作失败则会打印错误信息并退出程序。 V(int semid): 这个函数用于执行 V 操作即释放资源。它的实现与 P() 函数类似只是将 op.sem_op 设置为1表示对信号量执行 V 操作。 2.信号量实现同步互斥
交替实现奇偶数打印打印一个奇数后必须是一个偶数
#include stdio.h
#include stdlib.h
#include unistd.h
#include sys/types.h
#include sys/ipc.h
#include sys/sem.h#define KEY 1234 // 信号量的键值// 定义一个联合体用于semctl初始化
union semun {int val;struct semid_ds *buf;unsigned short *array;
};// 创建一个信号量并初始化为1
int create_semaphore()
{int semid semget(KEY, 1, IPC_CREAT | 0666); // 创建一个信号量集包含1个信号量if (semid -1) {perror(semget);exit(1);}union semun arg;arg.val 0; // 初始值为0if (semctl(semid, 0, SETVAL, arg) -1) // 初始化信号量{ perror(semctl);exit(1);}return semid;
}// P操作等待资源
void P(int semid)
{struct sembuf op;op.sem_num 0; // 信号量集中的第一个信号量op.sem_op -1; // 对信号量执行P操作op.sem_flg 0;if (semop(semid, op, 1) -1) {perror(semop);exit(1);}
}// V操作释放资源
void V(int semid)
{struct sembuf op;op.sem_num 0; // 信号量集中的第一个信号量op.sem_op 1; // 对信号量执行V操作op.sem_flg 0;if (semop(semid, op, 1) -1) {perror(semop);exit(1);}
}int main()
{int i 1;int j 2;int semid create_semaphore(); // 创建信号量pid_t pid fork(); // 创建子进程if (pid -1) {perror(fork);exit(1);}if (pid 0) // 子进程打印奇数{while(1){ printf(i %d\n,i);i 2;V(semid); // 释放资源sleep(1);} } else // 父进程打印偶数{while(1){P(semid); // 等待资源printf(j %d\n,j);j 2;} }return 0;
}执行结果 i 1 j 2 i 3 j 4 i 5 j 6 i 7 j 8 i 9 j 10 i 11 j 12 i 13 j 14 i 15 j 16 五、消息队列
发送进程
#include stdio.h
#include stdlib.h
#include unistd.h
#include sys/types.h
#include sys/ipc.h
#include sys/msg.h
#include string.h#define MSG_KEY 1234 // 消息队列的键值// 定义消息结构体
struct msg_buffer
{long msg_type; // 消息类型char msg_text[100]; // 消息内容
};int main()
{int msgid;struct msg_buffer message_send;// 创建消息队列msgid msgget(MSG_KEY, IPC_CREAT | 0666);if (msgid -1) {perror(msgget);exit(1);}// 准备发送的消息strcpy(message_send.msg_text, Hello, Message Queue!);message_send.msg_type 1; // 消息类型为1// 发送消息if (msgsnd(msgid, message_send, sizeof(message_send) - sizeof(long), 0) -1) {perror(msgsnd);exit(1);}printf(Parent process sent message: %s\n, message_send.msg_text);return 0;
}接收进程
#include stdio.h
#include stdlib.h
#include unistd.h
#include sys/types.h
#include sys/ipc.h
#include sys/msg.h
#include string.h#define MSG_KEY 1234 // 消息队列的键值// 定义消息结构体
struct msg_buffer {long msg_type; // 消息类型char msg_text[100]; // 消息内容
};int main()
{int msgid;struct msg_buffer message_rcv;// 创建消息队列msgid msgget(MSG_KEY, IPC_CREAT | 0666);if (msgid -1) {perror(msgget);exit(1);}// 接收消息if (msgrcv(msgid, message_rcv, sizeof(message_rcv) - sizeof(long), 1, 0) -1) {perror(msgrcv);exit(1);}printf(Child process received message: %s\n, message_rcv.msg_text);return 0;
}执行结果: ./s Parent process sent message: Hello, Message Queue! ./r Child process received message: Hello, Message Queue! 在这两个示例代码中主要使用了以下系统调用 msgget: 用于创建或打开一个消息队列。它接受一个参数即消息队列的键值一个唯一的标识符并返回一个消息队列的标识符msgid。 msgsnd: 用于向消息队列发送消息。它接受四个参数消息队列的标识符msgid、指向要发送的消息的指针、消息的大小不包括消息类型字段的大小、消息的标志通常为0。 msgrcv: 用于从消息队列接收消息。它接受五个参数消息队列的标识符msgid、指向用于接收消息的缓冲区的指针、缓冲区大小不包括消息类型字段的大小、消息类型通常为正整数、接收消息的标志通常为0。 msgctl: 用于控制消息队列的属性如删除消息队列。在这个示例中我们使用它来删除消息队列。它接受三个参数消息队列的标识符msgid、命令IPC_RMID 表示删除消息队列、指向用于控制消息队列属性的结构体的指针在这个例子中不需要。 六、套接字
网络部分的内容