Thread and Peocess

pthread_create()

原型:

int pthread_create(pthread_t* thread, pthread_attr_t* attr, void*(*start_routine)(void* ), void* args){};

其中:

thread: 标识一个线程,是一个pthread_t的变量,

typedef unsigned long int pthread_t

attr: 用于设置线程的属性.这里设为空,采用默认的属性

start_routine: 当线程的资源分配成功后,线程中运行的单元,(函数指针?类似于Java中的Runnable?估计可以是代码块或者是函数.)

arg: 线程函数运行时传入的参数,可以传入控制线程的变量.

成功创建线程则函数返回0,否则返回一个error,常见的error为:

EAGAIN: 表示系统中的线程数量达到了一个上限,

EINVAL: 表示线程的属性非法.

线程创建成功后,新创建的线程按照参数start_routine和args确定一个运行函数,原来的线程在线程创建函数返回后继续运行下一段代码.

pthread_join() && pthread_exit()

pthread_join()等待线程运行结束,是阻塞函数,一直到被等待的线程结束,函数返回并回收被等待线程的资源,函数原型为:

extern int pthread_join __p ((pthread_t __th, void ** __thread_return));

__th: 线程的标识符,即pthread_create()创建成功的值,

__thread_return: 线程返回值,是一个指针,用来存储被等待线程的返回值,线程可以返回一个指针.而这个参数是一个指向指针的指针,所以调用的时候通常是传递一个指针的地址.

一般来说可以先建立返回类型的指针,如int类型的指针,调用pthread_join(pt, (void*)&ret_join),就可以得到ret_join.

线程的属性

线程的属性结构

线程的属性结构体为pthread_attr_t, 在头文件<pthreadtypes.h>中:

typedef struct __pthread_attr_s
{
int __detachstate; /**线程的终止状态*/
int __schedpolicy; /**调度优先级*/
struct __sched_param __schedparam; /**参数*/
int __inheritsched; /**继承调度*/
int __scope; /**范围*/
size_t __guardsize; /**保证尺寸*/
int __stackaddr_set; /**运行栈*/
void *__stackaddr; /**运行栈地址*/
size_t __stacksize; /**线程运行大小*/
}pthread_attr_t

线程的属性不能直接设置,必须调用参数,常用的设置如线程的摘取状态,调度优先级,运行栈地址和大小,优先级等.而线程的初始化pthread_attr_init(),必须在create()前调用.

如线程的优先级状态由pthread_attr_getschedparam(),pthread_attr_setschedparam()两个函数设置,需要先get,写入,然后set.

#include <sched.h>
#include <pthread.h>
#include <stdio.h> pthread_attr_t attr;
pthread_t pt;
struct sched_param sch; pthread_attr_init(&attr);
pthread_attr_getschedparam(&attr, &sch);
sch.sched_priority = 256;
pthread_attr_setschedparam(&attr, &sch);
pthread_create(&pt, &attr, (void*)start_routine, &run);

线程的绑定状态,pthread_attr_setscope(),只有两个选择PTHREAD_SCOPE_SYSTEM, PTHREAD_SCOPE_PROCESS(非绑定).

pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

线程的分离状态,决定线程的终止方法,有分离和非分离两种.默认为非分离,在非分离状态下,线程只有遇到pthread_join()才是线程的结束,并释放资源;而分离线程,不需要等待其他线程,自身运行完就结束,马上释放资源.

设置函数为pthread_attr_setdetachstate():

int pthread_attr_setdetachstate(pthread_attr *attr, int detachstate);

detachstate有两个选择,PTHREAD_CREATE_DETACHED对应分离线程,PTHREAD_CREATE_JOINABLE对应非分离模式.

需要注意的是,如果线程运行的相当快,设置分离模式后,可能在pthread_create()返回前就执行完毕,因此有可能再次使用create()返回的线程号会出错.

(mutex 和 信号量 晚上补充 )

文件操作

文件描述符

Linux中每一个设备文件和普通文件,都对应一个整数型的文件描述符,所有对文件的操作都可以通过文件描述符实现.同时文件描述符也是内核空间和用户空间对文件和设备操作的接口.注意:文件描述符仅在一个进程内有效,即不同进程中的同一个设备或者文件可以对应不同的文件描述符,反之亦可.

Linux下有三个已经分配的文件描述符,也可以认为是系统保留的文件描述符,分别是标准输入,标准输出,标准错误;对应数字0,1,2. 所以很多时候重定向为0,1,2时,是传递的标准IO.

Open( ) & Create( )

两者都是成功应返回一个文件描述符,原型如下:

int open(const char *pathname, int flags);

int open(const char *pathname, int flags, mode_t mode);

使用时,应当包含的头文件为sys/types.h, sys/stat.h, fcntl.h

pathname: 是一个字符串变量,该变量的值在不同的系统下面不同,但是通常为1024字节.而如果给出的路径长度大于该数值,系统会对字符串截断,仅选择前面的部分执行.

flag: 是设置打开文件后允许对文件操作的方式.打开文件时必须是只读(O_RDONLY),只写(O_WRONLY),读写(O_RDWR)三种状态的一种,且通常定义为0,1,2.

除了必须设定的三种读写模式之外,还可以设置一些可选的参数项,如:

O_APPEND: 每次对文件的写入都追加到文件的末尾.

O_CREAT: 如果没有文件,就创建文件,且使用此选项就必须设置第三参数mode,作为新创建的文件的权限.

O_EXCL: 查看文件是否存在,如果同时指定了O_CREAT,而且文件已经存在,会返回错误,用这种方式可以安全打开一个文件.

O_TRUNC: 将文件的长度截断为0,如果文件存在,且文件成功打开,则会将其长度截断为0.通常是对文件进行清零操作的时候,选用这个参数.

O_NONBLOCK: 设置文件打开为非阻塞形式,默认为阻塞形式,即每次读写都需要返回状态.

mode就是用户,组成员,其他成员分别对文件的可读,可写,可执行的排列组合,具体可以百度.

一个O_CREAT和O_EXCL的容错的文件读写例子:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h> int main(void){
int fd = -1;
char filename[] = "test.txt"; /**打开文件,如果文件存在,则报错*/
fd = open(filename, O_RDWR|O_CREAT|O_EXCL,S_IRWXU);
if(fd == -1){
/**文件已经存在,重新打开*/
fd = open(filename, O_RDWR);
}else{
/**文件不存在,创建并打开*/
} return 0;
}

create()函数近似与open()的精简版本,原型为:

int create(const char* pathname, mode_t mode)
也可以近似理解为:
open(pathname, O_WRONLY|O_TRUNC, mode)

close()

原型为:

int close(int fd);

如果不关闭文件,系统在进程退出时,会自动关闭文件,但是不会收回文件描述符的值,这样在长时间后会因为达到文件描述符的最大上限而出现文件打开错误.

read()

read()从打开文件中读取数据,需要加入unistd.h,原型为:

ssize_t read(int fd, void* buf, size_t count);

从文件描述符中读取count字节,放到buf开始的缓冲区,count为0,读取为0,count大于SSIZE_MAX,结果不可预料.读取成功后,文件对应的读取位置指针向后偏移,大小为成功读取的字节数.

返回0说明达到文件末尾,返回-1代表读取错误,ssize_t可以定义为long或者为int.

write()

write()写入文件,其余参数同read().如果打开或者创建的文件带有O_APPEND属性,则每次写操作之前会将写操作的位置移动到文件的末尾.原型为:

ssize_t

(write 以及之后的问题暂时不补充)

进程间的通信

普通的半双工管道

在shell中使用 '|' 来标识,而在程序中用pipe(int[])来得到.

pipe是一个单向的IPC机制,限制有两点:

  1. 在普通的匿名管道中有缓冲区的限制,一般是在include/Linux/limits.h中定义,PIPE_BUF,

    POSIX.1定义该值不得小于512字节.
  2. 管道必须建立在父子进程或者是兄弟进程之间,不能在任意的两个进程中建立.

注意: 管道的阻塞性和原子性

对于一次写入管道内的数据小于128K,则是非阻塞的,当大于128K时,会阻塞直到读完成才会返回.并且在低于512的情况下,管道的读写是原子性的,而大于该值,多个线程向pipe写会造成数据覆盖.


int fd[2];
int status = pipe(fd); 这里的fd中,fd[0]是读的一端的文件描述符,fd[1]是写的一端的文件描述符,而如果真的需要通过pipe进行双工通信则必须建立两个管道.
通常需要在两个线程中分别关闭一个文件描述符.(主要是因为两个进程中都拿到了fd[],所以最好拿到即关掉不属于自己这端的文件描述符) int *write_fd = &fd[1];
int *read_fd = &fd[0]; pid_t pid;
pid = fork(); if(pid == -1){
printf("fork error \n");
}else if(pid == 0){
/*in the child process*/
close(*read_fd);
write(*write_fd, write_thing, write_length);
}else if(pid > 0){
/*in the parent process*/
close(*write_fd);
read(*read_fd, readbuffer, readbuffe_size);
}
这里还需要注意一点,必须先调用pipe()再调用fork(),否则子进程中无法继承得到文件描述符.

Thread and Peocess的更多相关文章

  1. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  2. 记一次tomcat线程创建异常调优:unable to create new native thread

    测试在进行一次性能测试的时候发现并发300个请求时出现了下面的异常: HTTP Status 500 - Handler processing failed; nested exception is ...

  3. 多线程爬坑之路-Thread和Runable源码解析

    多线程:(百度百科借一波定义) 多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提 ...

  4. Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory

    学习架构探险,从零开始写Java Web框架时,在学习到springAOP时遇到一个异常: "C:\Program Files\Java\jdk1.7.0_40\bin\java" ...

  5. Exception in thread "main" java.lang.NoSuchMethodError: org.objectweb.asm.ClassWriter.<init>(I)V

    在学习CGlib动态代理时,遇到如下错误: Exception in thread "main" java.lang.NoSuchMethodError: org.objectwe ...

  6. Thread.Sleep(0) vs Sleep(1) vs Yeild

    本文将要提到的线程及其相关内容,均是指 Windows 操作系统中的线程,不涉及其它操作系统. 文章索引 核心概念 Thread.Yeild       Thread.Sleep(0) Thread. ...

  7. Android笔记——Handler Runnable与Thread的区别

    在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一个类只要继承了Thread类同时覆写了本类中的run() ...

  8. Java Thread 的 sleep() 和 wait() 的区别

    Java Thread 的使用 Java Thread 的 run() 与 start() 的区别 Java Thread 的 sleep() 和 wait() 的区别       1. sleep ...

  9. Android线程管理之Thread使用总结

    前言 最近在一直准备总结一下Android上的线程管理,今天先来总结一下Thread使用. 线程管理相关文章地址: Android线程管理之Thread使用总结 Android线程管理之Executo ...

随机推荐

  1. sublime配置java环境

    今天突然不想用eclipse编写java了,觉得sublime挺好用,就想用sublime配置java环境,以下是过程以及出现的问题. 一.配置Java环境 1.打开我的电脑–属性–高级–环境变量 2 ...

  2. ShutdownHook作用

    源地址:http://kim-miao.iteye.com/blog/1662550 void java.lang.Runtime.addShutdownHook(Thread hook) 该方法用来 ...

  3. UVa 1627 Team them up! (01背包+二分图)

    题意:给n个分成两个组,保证每个组的人都相互认识,并且两组人数相差最少,给出一种方案. 析:首先我们可以知道如果某两个人不认识,那么他们肯定在不同的分组中,所以我们可以根据这个结论构造成一个图,如果两 ...

  4. Ubuntu 下编译libjingle-0.6.14 (转载)

    转自:http://blog.csdn.net/feifei454498130/article/details/8197103 添加依赖库: sudo apt-get install build-es ...

  5. SqlServer2012——快照

    1.数据库快照 优点: 维护历史数据以生成报表.由于数据库快照可提供数据库的静态视图,因而可以通过快照访问特定时间点的数据. 将查询实施在数据库的快照上,可以释放主体数据库上的资源. 数据库快照的限制 ...

  6. POJ3191【(-2)进制本质】

    题意: 实现10进制数转换成-2进制数 思路: 有点意思,先扯些题外话,一个我们经常做的二进制:利用二进制有好多优化,大多都是利用了二进制能够表示一个数,然后优化了空间或者时间. 所以问题很清楚啊,就 ...

  7. 渲染路径-实时渲染中常用的几种Rendering Path

    http://www.cnblogs.com/polobymulberry/p/5126892.html?utm_source=tuicool&utm_medium=referral 回到顶部 ...

  8. P1290-关灯

    描述 Description 宁智贤得到了一份有趣而高薪的工作.每天早晨她必须关掉她所在村庄的街灯.所有的街灯都被设置在一条直路的同一侧.宁智贤每晚到早晨5点钟都在晚会上,然后她开始关灯.开始时,她站 ...

  9. XML学习2 xml生产式

  10. hdu 6299 Balanced Sequence( 2018 Multi-University Training Contest 1 )

    #include <stdio.h> #include <iostream> #include <cstdlib> #include <cmath> # ...