应用程序设计

1 linux中文件编程两种方法:linux系统调用(依赖具体的操作系统)C语言库函数

库函数方式访问文件(2-1-1):库函数独立于操作系统;访问文件的库函数fopen fread fwrite fgetc fputc fprintf fscanf fseek mkdir;访问标准输入输出设备的库函数getch() putchar() printf();获取当前路径getcwd();参考如何按下任意键退出的代码;

系统调用方式访问文件(2-1-2)creat(filename mode) open() close() read() write() lseek() access()判断文件所具有的属性;文件描述符是打开文件时系统分配的非负整数;视频第11分钟讲解main函数参数argcargv的意义;最后有综合实例—-拷贝文件,可参考;

时间编程:跳过

2 进程控制理论(2-2-1):进程的三态,就绪态、执行态、阻塞态;进程互斥;进程同步,一组并发进程按一定顺序执行的过程称为进程间的同步。具有同步关系的一组并发进程称为合作进程,合作进程间互相发送的消息称为消息或事件。四种基本的进程调度算法。死锁的形成及预防。

3 有关进程的系统调用:pid_t getpid()获取当前正在运行的进程ID     pid_t fork()创建新进程,注意返回值,若小于0创建失败,对子进程返回0,对父进程返回子进程ID;问题:不同的进程有不同的用户空间,为什么子父进程能共享fork之后的代码而不是给子进程复制一份新的代码呢?而且接受返回值的变量pid应该在子父进程中分别占不同的内存空间吧?原来是数据空间和堆栈空间会从父进程得到一个拷贝,而不是共享。Yesvforkfork的区别,vfork创建的子进程与父进程共享数据段,且vfork后子进程先运行,而fork则不确定。Exec()函数族用被执行的新程序完全替换调用它的程序,进程的PID不会改变。Execl()的用途是运行某一个程序;execlp()execv();最后system()系统调用与前三个的区别。Wait()睡眠等待任意一个子进程退出,并返回子进程号;waitpid(pid,null,0)等待特定子进程退出。Exit(0)退出。Sleep(10)睡眠10秒。

4 进程间通信(2-3-1):作用,进程A给进程B传输数据、进程间共享资源、事件通知、进程控制。POSIX标准介绍,让应用程序能在不同的操作系统上运行。Linux使用的进程间通信方式,管道、信号、消息队列、共享内存、信号量、套接字;

5 管道(2-3-2):单向、先进先出,一个进程在管道尾写,另一个在管道头读,管道用于进程间单向传输数据;

无名管道:父子进程间通信,由int pipe(int filedis[2])创建,filedis(0)文件描述符接收管道头用于读,close(filedis[0])关闭头部,必须在fork()之前调用pipe(),这样子进程才能继承文件描述符。管道在内核空间有内核创建,只给用户空间俩个文件描述符来定位一头一尾。Fork之后子进程会拷贝和父进程一样的文件描述符,他们操作内核空间的同一个管道。示例程序疑问:父进程没写时,子进程就不能读吗,读空的话子进程会自动睡眠的呀,干嘛还人为地让子进程先睡眠几秒?这个程序要自己试验一下

有名管道FIFO(任意两个进程间通信)mkfifo(char *pathname, mode_t mode),他在磁盘上创建一个文件,不同于pipe在内核空间创建文件;open打开方式没使用O_NONBLOCK标志时,如果试图读取空的FIFO,则进程阻塞,使用了该标志,则返回读取出错信息。删除管道unlink(管道文件路径)pause()暂停,等待信号,具体用法还需百度。从命令行输入数组参数到函数,strcpy(w_buf,argv[1])。示例程序需要练习。

6 信号(2-3-3)unix中一种古老的进程通信机制。那些情况下产生信号:用户按键、硬件异常、kill函数、kill命令;信号的类型:SIGINT(Ctrl-C)SIGKILLSIGSTOP30种;信号处理方式:忽略、通知内核调用相关用户函数、执行系统默认动作(终止该进程);具体参考视频第14分钟,signo对应的执行方式在signal.h中定义;kill(pid_t pid, int signo)即可给别的进程也可给自身发信号(并不一定是发SIGKILL信号)pid的几种取值范围可表示不同的通信情况,如大于0小于0等等情况;raise(int signo)只给自身发;alarm(unsigned int seconds)在指定秒数后给进程自身发送SIGALRM信号;pause(void)使调用进程挂起直至捕捉到一个信号。注册信号处理函数signal(signo,my_func),注册并不是执行,而是将来收到信号时由内核调用注册的自定义函数;my_func若替换为SIG_IGN则是忽略此信号,SIG_DFL则是系统默认方式处理;自定义函数my_func(signo);具体用法查看示例程序;ps aux命令查看进程ID;用命令发送信号kill –s SIGQUIT 3687

7 共享内存(2-3-4):优点,访问快;两步,创建int shmget()返回共享内存标志符(对所有进程唯一)、映射int shmat()返回共享内存映射到进程空间的地址、共享内存从进程中脱离int shmdt();具体函数参数的使用参考示例程序;int shmat(int shmid,char *shmaddr,int flag)返回值是映射得到的线性地址,shmid是共享内存IDshmaddr是指定的映射起始线性地址,为0表示系统自动分配,flag一般为0;疑问:是否可以用于任意进程间通信?

8 消息队列(2-4-1)是一个消息的链表,区别于信号和管道的作用是信息有一定格式。key_t ftok(char* pathname, char proj)获得文件名对应的键值,懒得看了;

9 信号量,略;‘

10 多线程优势:不同进程使用独立的数据段和堆栈,而同一进程下的线程可以共享数据段和堆栈;而fork创建的父子进程恰好相反,共享代码段,不同的数据段和堆栈段;多个线程共享用户空间,切换花销少;疑问:不同进程不是有独立的用户空间吗,那父子进程共享代码段怎么算?支持POSIX接口;创建线程,int pthread_creat(pthread_t *tidp,const pthread_attr_t *attr,void *(*start)(void),void *arg),创建成功则返回正数,反之为0tidp为线程IDattr进程属性一般为空即nullstart为线程执行的函数,arg为该函数需要的参数;头文件要包含pthread.h,编译时要加上gcc filename.c –lpthread –o filenamereturn (void *) 0整型也是32位的吗?数据要定义在所有程序开头,才是全局的,才对主函数、线程都可见;进程中任何一个线程调用exit_exit,整个进程都退出;线程正常退出方式,return返回、调用pthread_exit()函数;非正常退出,其它线程干预或自身运行出错时退出;pthread_join(tidp,null)阻塞调用线程,等待线程tidp退出,null那个位置是void *型参数其实用来接收返回值的地址的。进程创建了线程之后首先是要去运行进程的。获取线程标志,pthread_t pthread_self(void)返回值其实是unsigned int;线程是属于进程的,在线程中调用getpid()得到线程所属的进程ID;线程非正常退出的话,释放资源的代码该放在什么位置,解决方法:pthread_cleanup_push(func_name,func_parameter)将清理函数入栈、pthread_cleanup_pop(int)将清理函数出栈,参数表示代码运行到pop时需不需要执行堆栈中的函数,为0表示若中间没有退出则不执行了;为1表示还是要执行,尽管前面没有退出;二者中间任何位置非正常退出或者通过pthread_exit()退出前(不包括return)都将调用pthread_cleanup_push()指定的函数来释放资源;二者的参数见示例程序;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值