概念:正在执行的程序(每个进程都有一个ID);
进程ID为1的通常是init进程,init进程(大哥完了,那么整个帮派都奔溃了)绝不会终止;
结构:linux下进程结构;
fork()系统调用:(多进程)
重点:一次调用,返回两次,父进程返回的是子进程的ID,子进程返回的是0;
父子进程交替执行,任何一个进程都必须要有父进程;
理解僵进程和孤儿进程;
fork()简单实现
Pid_tpid=fork();
If(pid==0)
{ }
Else(pid>0)
{ }
Else
{ printf(“error”); return -1; }
exec族函数:(替换进程)
int execl(constchar *path, const char *arg, ...);
int execlp(constchar *file, const char *arg, ...);
int execle(const char *path, const char *arg , ..., char * const envp[]);
int execv(constchar *path, char *const argv[]);
int execvp(constchar *file, char *const argv[]);
Example:execlp("ps","ps","-ax",0);
system函数:(启动新进程)
int system(const char *string);
String是你要启动程序的名称;
Example:system("ps -ef");
wait: pid_t wait(int * status) ;
waitpid: pid_t waitpid(pid_t pid,int * status, int options) ;
守护进程:守护进程是生存期长的一种进程。它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件,在后台运行不受终端控制的进程。(就像一些小说里守护某些古宝的神兽)
2.IPC进程通信
1. 信号:(通知、进程同步)black宇笔记:有点像单片机里的中断
void (*signal(int sig, void (*func)(int))) (int);
信号分为可靠信号(实时信号都支持排队)和不可靠信号(非实时信号都不支持排队)。
2. 管道:(传输数据)
概念:把从一个进程连接到另一个进程的一个数据流称为一个“管道”。
pipe()函数:创建一无名管道int pipe(int file_descriptor[2]);
fcntl()函数;
FIFO命名管道:
int mkfifo(constchar *filename,mode_t mode);
int mknod(constchar *filename,mode_t mode|S_IFIFO,(dev_t) 0);
管道读写规则:(网络通信规则和管道一样)
Ø 如果试图从管道写端读取数据,或者向管道读端写入数据都将导致错误发生。(端口用反)
Ø 当没有数据可读时,read调用就会阻塞,即进程暂停执行,一直等到有数据来到为止。(无数据可读-读端阻塞)
Ø 如果管道的另一端已经被关闭,也就是没有进程打开这个管道并向它写数据时,read调用就会阻塞。(写端关闭-读端阻塞)
Ø 如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。(读进程不读-写端阻塞)
Ø 如果管道的写端不存在,则认为已经读到了数据的末尾,读函数返回的读出字节数为0。(写端不存在-返回零)
Ø 当管道的写端存在时,如果请求的字节数目大于PIPE_BUF,则返回管道中现有的数据字节数。(请求数过大-返回现有的字节数)
读端关闭,写端一直写产生管道破裂
black宇笔记:读端:无数据可读-读端阻塞 写端关闭-读端阻塞
写端:读进程不读-写端阻塞 写端不存在-返回零 读端关闭写端一直写-管道破裂
其他:请求数过大-返回现有的字节数 端 口用反-出错
3. 消息队列:(传输数据)
int msgget(key_tkey, int msgflg); //创建消息队列:
int msgsnd(int msgid,const void *msg_ptr,size_t msg_sz,int msgflg);//添加消息队列
int msgrcv(int msgid, void*msg_ptr,size_t msgsz,long int msgtype,int msgflg);//消息队列里检索消息
int msgctl(int msqid,intcommand,strcut msqid_ds *buf);//消息队列的控制函数
4. *共享内存:(传输数据)
int shmget(key_t key,size_tsize, int shmflg);// 创建共享内存
void *shmat(int shmid, const void *shmaddr, int shmflg);// 共享内存段连接到某个进程的地址空间
int shmdt(const void*shm_addr);// 共享内存与当前进程脱离
int shmctl(int shm_id,intcommand, struct shmid_ds *buf);// 共享内存的控制函数
5. *信号量:(进程同步,功能比信号好点)
int semget(key_t key,int num_sems,int sem_flag);// 创建信号量
int semop ( int sem_id,struct sembuf*sem_ops,size_t num_sem_ops,);// 改变信号量键值
int semctl(int sem_id,int sem_num,int command,);// 允许我们直接控制信号量的信息
3.容器
容器都有哪些呢?
向量(vector)、双端队列(deque)、列表(list)、集合(set)、多重集合(multiset)、映射(map)和多重映射(multimap)
2.向量(vector)
(1)特点:(1)对序列的快速随机访问(2)数据结构很像一个数组,vector能非常方便和高效访问单个元素(3) 动态结构,向量的内存用尽时,向量自动分配更大的连续内存区
(2)基本操作:头文件:#include<vector>创建vector对象:vector <数据类型>name 尾部插入数据:name.push_back(a) 使用下标访问元素:cout<<name[0]<<endl 使用迭代器访问元素: vector<int>iteratorit;
for(it = name.begin;it!=name.end;it++)
cout<<*it<<endl;
插入元素:name.insert(name.begin()+i,a) 在i+1个元素前加入a 删除元素:vec.erase(vec.begin()+2):删除第3个元素vec.erase(vec.begin()+i,vec.end()+j):删除区间[i,j-1]区间从0开始 向量大小: vec.size();vec.resize;改变大小 清空:vec.clear();
3.列表(list)
(1) 相对于vector的优势:可以存放双向链表,元素的插入删除操作很高效
(2) 来段代码练练手
4.映射(map)
(1) 使用
#include<map>
map<int,string> personnel;
//用int作为索引,存储string对象