atoi 函数概述
atoi(ASCII to Integer)是C/C++标准库中的一个函数,用于将字符串转换为整型数值。定义在头文件 <stdlib.h>(C)或 <cstdlib>(C++)中。
int atoi(const char *str);
作业:
聊天
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
void* th1(void* arg)
{
int fd = *(int*)arg;
while(1)
{
char buf[100]={0};
read(fd,buf,sizeof(buf));// #quit\\n
if(0== strcmp(buf,"#quit\\n"))
{
//break;
exit(0);
}
printf("from B:%s",buf);
fflush(stdout);
}
return NULL;
}
void* th2(void* arg)
{
int fd = *(int*)arg;
while(1)
{
char buf[100]={0};
printf("to B:");
fgets(buf,sizeof(buf),stdin); // #quit\\n
write(fd,buf,strlen(buf));
if(0 == strcmp(buf,"#quit\\n"))
{
exit(0);
}
}
return NULL;
}
int main(int argc, char **argv)
{
int ret = mkfifo("myfifo1", 0666);
if (-1 == ret)
{
if (EEXIST == errno) // 管道已经存在的错误
{
//
}
else
{
perror("mkfifo");
return 1;
}
}
ret = mkfifo("myfifo2", 0666);
if (-1 == ret)
{
if (EEXIST == errno) // 管道已经存在的错误
{
//
}
else
{
perror("mkfifo");
return 1;
}
}
// open 会阻塞
int fd_w = open("myfifo1", O_WRONLY);
if (-1 == fd_w)
{
perror("open myfifo1");
return 1;
}
// open 会阻塞
int fd_r = open("myfifo2", O_RDONLY);
if (-1 == fd_r)
{
perror("open myfifo2");
return 1;
}
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,th1,&fd_r);
pthread_create(&tid2,NULL,th2,&fd_w);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#define MAX 19661
int main(int argc, char** argv)
{
int fd[2] = {0};
// 创建匿名管道,打开管道文件
int ret = pipe(fd);
if (-1 == ret)
{
perror("pipe");
return 1;
}
pid_t pid = fork();
if (pid > 0)
{
// 父进程,关闭读段
close(fd[0]);
int fd_dict = open("/home/linux/dict.txt", O_RDONLY);
if (-1 == fd_dict)
{
perror("open dict");
return 1;
}
while (1)
{
while (1)
{
char buf[4096] = {0};
int rd_ret = read(fd_dict, buf, sizeof(buf));
if (rd_ret == 0)
{
break;
}
write(fd[1], buf, rd_ret); // 最终的退出条件,管道破裂
}
lseek(fd_dict, 0, SEEK_SET); //回到文件的开头
}
close(fd_dict);
}
else if (0 == pid)
{
// 子进程,关闭写段
close(fd[1]);
FILE* fp = fdopen(fd[0], "r");
while (1)
{
int num = 0;
char line_buf[1024] = {0};
char want_word[50] = {0};
printf("input word:");
fgets(want_word, sizeof(want_word), stdin); // hello\\0
want_word[strlen(want_word) – 1] = '\\0';
if (0 == strcmp(want_word, "#quit"))
{
break;
}
while (1)
{
// read(fd[0],line_buf,sizeof(line_buf));
fgets(line_buf, sizeof(line_buf), fp);
char* word = strtok(line_buf, " ");
char* mean = strtok(NULL, "\\r");
if (0 == strcmp(word, want_word))
{
printf("%s %s\\n", word, mean);
break;
}
num++;
if (num >= MAX)
{
printf("can't find,%s\\n", want_word);
break;
}
}
}
exit(0);
}
else
{
perror("fork");
return 1;
}
return 0;
}
一、信号通信(异步通信)
异步通信:支持处理随机事件的能力。

查信号:kill -l(1-31号给./a.out;Linux操作系统信号 34 – 64)
查手册:man 7 signal
2号SIGINT:Ctrl C
kill -X XXXXX
发送进程 信号 接收进程
kill -9 1000
a.out 9 1000
Term:终止,请求进程正常退出
lgn:忽略信号
Core:默认行为是终止进程并生成核心转储文件
Stop:停止进程
Cont:继续,该信号用于恢复被暂停的进程。
发送端
#include <sys/types.h
>#include <signal.h>
int kill(pid_t pid, int sig);
功能:通过该函数可以给pid进程发送信号为sig的系统信号。
参数:pid要接收信号的进程pidsig 当前程序要发送的信号编号《===kill -I
返回值:成功0;失败-1。
int main(int argc, char *argv[])
{
if(argc < 3)
{
return 1;
}
pid_t pid = atoi(argv[1]);
int num = atoi(argv[2]);
int ret = kill(pid,num);
if(-1 == ret)
{
perror("kil");
return 1;
}
return 0;
}
unsigned int alarm(unsigned int seconds); == SIGALAM
功能:定时由系统给当前进程发送信号也称为闹钟函数。
闹钟只有一个,定时只有一次有效,但是必须根据代码逻辑是否执行判断
int pause(void);
功能:进程暂停,不再继续执行,除非收到其他信号(信号是被捕获过)
sighandler_t signal(int signum,sighandler_t handler);
功能:修改进程中,signum对应的处理函数(系统中默认提供的那个)。
参数:signum,需要修改函数的对应的信号数。
handler,需要替换的函数的函数名。
有二个宏表示:SIG_DFL表示默认处理;SIG_IGN表示忽略处理
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
int flag = 0 ;
void handle(int num)
{
flag = 1;
}
int main(int argc, char *argv[])
{
signal(SIGALRM,handle);
//设置一个闹钟,5s 后,系统送信号给当前进程
alarm(5);
while(1)
{
if(0 == flag)
{
printf("i'm process…\\n");
}
else
{
printf("i'm sleep…\\n");
}
sleep(1);
}
return 0;
}
}
发信号kill -18 24144
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
void handle(int num)
{
}
int main(int argc, char *argv[])
{
signal(SIGCONT,handle);
int i = 0 ;
while(1)
{
printf("i'm process…,pid :%d\\n",getpid());
sleep(1);
i++;
if(5==i)
{
pause(); //进程暂停
}
}
return 0;
}
SIGUSR1系统给用户,预留的信号,自定义的信号
SIGUSR2
SIGCHLD :父子进程中,当子进程退出后,给父进程发送的信号。用于父进程回收子进程
资源。
SIGKILL 9强制关闭以及进程
SIGSTOP 19强制咱体以及进程SIGALAM定时器,定时时间到达,由系统发给对应的进程
SIGINT,2,默认ctr1+C发送给进程的,就是这个信号。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
void handle1(int num)
{
static int i = 0 ;
printf("老爸,叫你…\\n");
i++;
if(3 == i)
{
signal(SIGUSR1,SIG_IGN); // 忽略user1 信号
}
}
void handle2(int num)
{
static int i = 0 ;
printf("老妈,叫你…\\n");
i++;
if(5 == i)
{
signal(SIGUSR2,SIG_DFL); // user2 信号处理 回复默认,默认是关闭
}
}
int main(int argc, char *argv[])
{
signal(SIGUSR1,handle1);
signal(SIGUSR2,handle2);
while(1)
{
printf("i'm playing…,pid:%d\\n",getpid());
sleep(1);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
void handle(int num)
{
pid_t ret = wait(NULL);
printf("recycle pid:%d\\n",ret);
}
int main(int argc, char *argv[])
{
// SIGCHLD ,对于父进程而言,默认情况是忽略
// 当子进程结束后,会由系统 给父进程发送 SIGCHLD 这个信号。
signal(SIGCHLD,handle);
pid_t pid = fork();
if(pid>0)
{
while(1)
{
printf("father ,i'm processing…pid:%d\\n",getpid());
sleep(1);
}
}
else if(0 ==pid)
{
int i=3;
while(i–)
{
printf("child ,i'm processing…,pid:%d\\n",getpid());
sleep(1);
}
exit(0);
}
else
{
perror("fork");
return 1;
}
return 0;
}
二、共享内存
共享内存==》效率最高的进程间通信方式
操作流程:key==》申请对象==》映射对象==》读写对象==》撤销映射==》删除对象
1、key值
key_t ftok(const char *pathname,int proj_id);
功能:通过该函数可以将pathname指定的路径用来以proj_id生成唯一的临时键值。
参数:pathname路径+名称===任意文件,只要不会被删除重建即可。
proj_id整形的数字,一般用ASCII码的单字符表示与参数1的运算。
返回值:成功返回唯一健值失败-1
2、申请对象:shmget()
#include <sys/ipc.h>
#include <sys/shm.h>
ps auxlgrep a.out
share memory get IPC_CREAT|0666
int shmget(key_t key, size_t size, int shmflg);
功能:使用唯一键值key向内核提出共享内存使用申请
参数:key唯一键值
size要申请的共享内存大小
shmflg 申请的共享内存访问权限,八进制表示
如果是第一个申请,则用IPC_CREAT
如果要检测是否存在,用IPC_EXCL
返回值:成功 返回共享内存id,一般用shmid表示;失败-1。
3、映射对象:
shmat()
void *shmat(int shmid,const void *shmaddr, int shmflg);
功能:将指定shmid对应的共享内存映射到本地内存。
参数:shmid要映射的本地内存
shmaddr本地可用的地址,如果不确定则用NULL,表示由系统自动分配。
shmf1g0,表示读写SHM_RDONLY,只读
返回值:成功返回映射的地址,一般等于shmaddr失败(void*)-1
4、共享内存的读写:
strcpy,字符串
memcpy,二进制数据
共享内存和管道区别
1.共享内存就是一段内存区域,管道底层实现是队列。
2.共享内存可以指定大小。没有写阻塞,写入数据的大小,大于共享内存的大小,就越界了。没读阻塞,如果写段没有写入数据的话,会读到随机数据。
3.数据会一致保留
共享内存
ipcs -a 查询共享内存,信号量集,消息队列
ipcrm -m删除共享内存
-s删除信号量集
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main(int argc, char **argv)
{
// 1 ,申请key 值
key_t key = ftok("./", '#');
if (-1 == key)
{
perror("ftok");
return 1;
}
printf("key is %d\\n", key);
// 2.申请共享内存
int shmid = shmget(key, 4096, IPC_CREAT | 0666);
if (-1 == shmid)
{
perror("shmget");
return 1;
}
// 3.映射内存 ,映射到用户空间(0~3G) ,可以读写
void *p = shmat(shmid, NULL, !SHM_RDONLY);
if ((void *)-1 == p)
{
perror("shmat");
return 1;
}
// 4.内存写入数据
strcpy(p, "hello world");
// memcpy(p,"hello world",12);
/*// 4.从共享内存读出数据
// strcpy(p, "hello world");
// memcpy(p,"hello world",12);
printf("shm:%s\\n", (char *)p);
// 5.断开映射关系
shmdt(p);
// 6 .删除共享内存
// shmctl(shmid,IPC_RMID,NULL);
*/
//5.断开映射关系
shmdt(p);
return 0;
}





