作業1
司機: 接收售票員關門信號-->開車 //SIGUSR1
接收到站信號-->停車 //SIGINT
發送開門信號給售票員-->等待關門信號 //pause() 掛起進程
售票員:發送關門信號
接收開門信號-->開門 //SIGUSR2
#include <stdio.h>
#include <string.h>
#include <unistd.h> //fork ()
#include <stdlib.h>
#include <sys/types.h> //kill()
#include <signal.h> //signal()
pid_t pid = -1;
//司機:到站停車 --> SIGINT ctrl+c
// 關門開車 --> SIGUSR1
void handleDriver(int sig)
{
if (SIGINT == sig)
{
printf("到站了...\\n");
sleep(1);
printf("司機開始停車...\\n");
sleep(1);
int ret = 0;
ret = kill(pid, SIGUSR2); //發送信號給售票員讓她開門
if (-1 == ret)
{
perror("kill");
}
}
else if (SIGUSR1 == sig)
{
printf("司機開始開車...\\n");
sleep(1);
printf("車正在跑...\\n");
sleep(1);
}
}
//售票員:開門 -->SIGUSR2
void handleConductor(int sig)
{
if (SIGUSR2 == sig)
{
printf("售票員開門...\\n");
sleep(1);
printf("乘客上車...\\n");
sleep(1);
printf("售票員關門...\\n");
sleep(1);
kill(getppid(), SIGUSR1); //售票員發送信號給司機開車
}
}
int main(void)
{
pid = fork();
if (pid > 0) //driver
{
signal(SIGINT, handleDriver);
signal(SIGUSR1, handleDriver);
printf("司機等待售票員做好開車準備...\\n");
while (1)
{
pause();
}
}
else if (0 == pid) //conductor
{
signal(SIGINT, SIG_IGN);
signal(SIGUSR2, handleConductor);
sleep(1);
//發送一個開車信號讓其開車
kill(getppid(), SIGUSR1);
while (1)
{
pause();
}
}
else if (-1 == pid)
{
perror("fork");
return -1;
}
return 0;
}
運行結果:
1.PNG
創建線程
#include <pthread.h> //pthread_create()
#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h> //errno
#include <unistd.h>
void *thread_run(void *arg)
{
while (1)
{
printf("this is thread_run...\\n");
sleep(1);
}
return NULL;
}
int main(void)
{
pthread_t thread;
int ret = 0;
ret = pthread_create(&thread, NULL, thread_run, NULL);
if (0 != ret)
{
printf("errno:%d, error:%s\\n", ret, strerror(ret));
return -1;
}
while (1)
{
printf("this is main...\\n");
sleep(1);
}
return 0;
}
運行結果:
2.PNG
pthread_arg.c
#include <pthread.h> //pthread_create()
#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h> //errno
#include <unistd.h>
typedef struct Student
{
int iId;
char caName[32];
float fScore;
}Student;
void *thread_run(void *arg)
{
while (1)
{
//printf("this is thread_run...arg = %d\\n", *(int *)arg);
//printf("this is thread_run...arg = %d\\n", (int)arg);
Student *pStu = (Student *)arg;
printf("id:%d, name:%s, score:%.2f\\n"
, pStu->iId, pStu->caName, pStu->fScore);
sleep(1);
}
return NULL;
}
int main(void)
{
pthread_t thread;
int ret = 0;
int iArg = 1888;
//ret = pthread_create(&thread, NULL, thread_run, &iArg);
//ret = pthread_create(&thread, NULL, thread_run, (void *)iArg);
//ret = pthread_create(&thread, NULL, thread_run, (void *)1888);
Student stu = {1001, "zhangsan", 89};
ret = pthread_create(&thread, NULL, thread_run, &stu);
//ret = pthread_create(&thread, NULL, thread_run, (void *)stu); //error
if (0 != ret)
{
printf("errno:%d, error:%s\\n", ret, strerror(ret));
return -1;
}
while (1)
{
printf("this is main...\\n");
pause();
}
return 0;
}
運行結果:
1.PNG
pthread_cancel_exit.c
#include <pthread.h> //pthread_create()
#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h> //errno
#include <unistd.h>
void *thread_run(void *arg)
{
//在線程函數中調用pthread_setcancelstate來設置
//不同意結束線程請求,阻塞線程結束請求
//直到線程允許接收線程結束請求
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
while (1)
{
printf("this is thread_run...\\n");
sleep(1);
//break;
//結束所屬線程
//pthread_exit(NULL);
}
return NULL;
}
int main(void)
{
pthread_t thread;
int ret = 0;
ret = pthread_create(&thread, NULL, thread_run, NULL);
if (0 != ret)
{
printf("errno:%d, error:%s\\n", ret, strerror(ret));
return -1;
}
sleep(3);
//發送一個結束線程請求給指定的線程
//默認情況下,線程會同意該結束線程請求
//還可以設置不同意
//pthread_cancel(thread);
//若存在主線程中,如果含有其他線程存在,
//則阻塞等待線程的結束
//若沒有其他線程,則結束程序
pthread_exit(NULL);
while (1)
{
printf("this is main...\\n");
sleep(1);
}
return 0;
}
運算結果:
1.PNG
pthread_exit.c
#include <pthread.h> //pthread_create()
#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h> //errno
#include <unistd.h> //sleep()
#include <stdlib.h> //exit()
//一個進程創建線程后,創建的線程從屬于該進程
//不獨立于進程,共享進程的所有資源
//線程是最小的執行單元,
//若一個進程沒有創建線程,我們既可以把它看做是進程,也可以是相當于線程
//若一個進程創建線程后,我們可以將該進程稱之為主線程
//一個進程可以創建多個線程,線程之間資源共享
void *thread_run(void *arg)
{
int i = 0;
while (1)
{
printf("this is thread_run...\\n");
sleep(1);
i++;
if (5 == i)
{
//使用return 只能結束當前線程
//return NULL;
//會將該線程所屬的進程掛掉,當然線程也會掛掉
exit(1);
}
}
return NULL;
}
int main(void)
{
pthread_t thread;
int ret = 0;
ret = pthread_create(&thread, NULL, thread_run, NULL);
if (0 != ret)
{
printf("errno:%d, error:%s\\n", ret, strerror(ret));
return -1;
}
while (1)
{
printf("this is main...\\n");
sleep(1);
}
return 0;
}
運算結果:
1.PNG
pthread_join.c
#include <pthread.h> //pthread_create()
#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h> //errno
#include <unistd.h>
void *thread_run(void *arg)
{
while (1)
{
printf("this is thread_run...\\n");
sleep(1);
}
return NULL;
}
int main(void)
{
pthread_t thread;
int ret = 0;
ret = pthread_create(&thread, NULL, thread_run, NULL);
if (0 != ret)
{
printf("errno:%d, error:%s\\n", ret, strerror(ret));
return -1;
}
//等待線程結束,若線程在運行,則阻塞等待
//若線程結束,立即返回
//第一個參數:要等待的線程
//第二個參數:要來獲得線程的返回值
pthread_join(thread, NULL);
while (1)
{
printf("this is main...\\n");
sleep(1);
}
return 0;
}
運算結果:
1.PNG
pthread_mutex.c
#include <pthread.h> //pthread_create()
#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h> //errno
#include <unistd.h>
pthread_mutex_t mutex; //互斥量--鎖
int g_iData = 0;
void *thread_run(void *arg)
{
while (1)
{
//使用pthread_mutex_lock和pthread_mutex_unlock
//使它們之間的語句合成原子操作
//若其他線程沒有釋放該互斥量
//則本線程阻塞等待
//pthread_mutex_lock(&mutex);
//pthread_mutex_trylock(&mutex);
++g_iData;
printf("thread:data = %d\\n", g_iData);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main(void)
{
//初始化互斥量,NULL表示使用默認屬性初始化該互斥量
pthread_mutex_init(&mutex, NULL);
pthread_t thread;
int ret = 0;
ret = pthread_create(&thread, NULL, thread_run, NULL);
if (0 != ret)
{
printf("errno:%d, error:%s\\n", ret, strerror(ret));
return -1;
}
while (1)
{
pthread_mutex_lock(&mutex);
++g_iData;
printf("main:data = %d\\n", g_iData);
pthread_mutex_unlock(&mutex);
}
return 0;
}
運算結果:
2.PNG
pthread_share
#include <pthread.h> //pthread_create()
#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h> //errno
#include <unistd.h>
int g_iData = 999;
void *thread_run(void *arg)
{
//while (1)
{
printf("this is thread_run...iData = %d\\n", g_iData);
g_iData++;
//sleep(1);
}
return NULL;
}
int main(void)
{
pthread_t thread;
int ret = 0;
ret = pthread_create(&thread, NULL, thread_run, NULL);
if (0 != ret)
{
printf("errno:%d, error:%s\\n", ret, strerror(ret));
return -1;
}
sleep(2);
// while (1)
{
printf("this is main...iData = %d\\n", g_iData);
// sleep(1);
}
return 0;
}
運算結果:
1.PNG
read_stu
#include <stdio.h>
#include <unistd.h> //write() read()
#include <errno.h> //errno
#include <string.h> //strerror()
/*open()*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h> //pthread_create
pthread_mutex_t mutex;
#define NAME_LEN 32
typedef struct Student
{
int iId;
char caName[NAME_re LEN];
char cSex;
float fScore;
}Student;
int myOpen(const char *pathname)
{
int fd = -1;
if (NULL != pathname)
{
fd = open(pathname, O_RDONLY | O_CREAT
, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (-1 == fd)
{
printf("open error: %s\\n", strerror(errno));
}
}
return fd;
}
int g_iSign = 0;
void *read_thread(void *arg)
{
int fd = -1;
fd = myOpen("stu.info");
if (-1 != fd)
{
int ret = -1;
Student *pStu = (Student *)arg;
while (1)
{
if (0 == g_iSign)
{
pthread_mutex_lock(&mutex);
memset(pStu, '\\0', sizeof(Student));
ret = read(fd, pStu, sizeof(Student));
if (0 == ret)
{
printf("reached the file end\\n");
pthread_mutex_unlock(&mutex);
g_iSign = 1;
break;
}
else if (-1 == ret)
{
printf("read error:%s\\n", strerror(errno));
pthread_mutex_unlock(&mutex);
g_iSign = 1;
break;
}
pthread_mutex_unlock(&mutex);
g_iSign = 1;
}
}
close(fd);
}
return NULL;
}
void *print_thread(void *arg)
{
Student *pStu = (Student *)arg;
int i = 0;
while (1)
{
if (1 == g_iSign)
{
pthread_mutex_lock(&mutex);
if (0 == pStu->iId)
{
pthread_mutex_unlock(&mutex);
break;
}
printf("id:%d, name:%s, sex:%c, score:%.1f\\n"
, pStu->iId, pStu->caName
, pStu->cSex, pStu->fScore);
pthread_mutex_unlock(&mutex);
g_iSign = 0;
}
}
return NULL;
}
int main(void)
{
pthread_mutex_init(&mutex, NULL);
Student stu;
pthread_t pthr_read;
pthread_t pthr_show;
pthread_create(&pthr_read, NULL, read_thread, &stu);
pthread_create(&pthr_show, NULL, print_thread, &stu);
pthread_join(pthr_read, NULL);
pthread_join(pthr_show, NULL);
return 0;
}
運算結果:
3.PNG
write_stu.c
#include <stdio.h>
#include <unistd.h> //write()
#include <errno.h> //errno
#include <string.h> //strerror()
/*open()*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define NAME_LEN 32
typedef struct Student
{
int iId;
char caName[NAME_LEN];
char cSex;
float fScore;
}Student;
int myOpen(const char *pathname)
{
int fd = -1;
if (NULL != pathname)
{
fd = open(pathname, O_WRONLY | O_CREAT | O_TRUNC
, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (-1 == fd)
{
printf("open error: %s\\n", strerror(errno));
}
}
return fd;
}
int main(void)
{
int fd = -1;
fd = myOpen("stu.info");
if (-1 != fd)
{
Student stu[6] = {{1001, "zhangsan", 'f', 99}
, {1002, "lisi", 'm', 79}
, {1003, "wangwu", 'f', 89}
, {1004, "zhaoliu", 'm', 69}
, {1005, "xiaoqi", 'm', 79}
, {1006, "laoba", 'f', 89}};
int ret = -1;
int i = 0;
for (; i < 6; i++)
{
ret = write(fd, stu+i, sizeof(Student));
if (-1 == ret)
{
printf("write error: %s\\n", strerror(errno));
}
else
{
printf("write %d bytes to file\\n", ret);
}
}
}
return 0;
}
1.PNG
sem_read_stu.c
#include <stdio.h>
#include <unistd.h> //write() read()
#include <errno.h> //errno
#include <string.h> //strerror()
/*open()*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h> //pthread_create
#include <semaphore.h>
pthread_mutex_t mutex;
sem_t read_sem; //整形
sem_t show_sem;
#define NAME_LEN 32
typedef struct Student
{
int iId;
char caName[NAME_LEN];
char cSex;
float fScore;
}Student;
int myOpen(const char *pathname)
{
int fd = -1;
if (NULL != pathname)
{
fd = open(pathname, O_RDONLY | O_CREAT
, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (-1 == fd)
{
printf("open error: %s\\n", strerror(errno));
}
}
return fd;
}
void *read_thread(void *arg)
{
int fd = -1;
fd = myOpen("stu.info");
if (-1 != fd)
{
int ret = -1;
Student *pStu = (Student *)arg;
while (1)
{
//如果read_sem大于0,接著往下執行,并且將該變量減一
//如果read_sem等于0,則阻塞,直到該值大于0
sem_wait(&read_sem);
pthread_mutex_lock(&mutex);
memset(pStu, '\\0', sizeof(Student));
ret = read(fd, pStu, sizeof(Student));
if (0 == ret)
{
printf("reached the file end\\n");
pthread_mutex_unlock(&mutex);
sem_post(&show_sem);
break;
}
else if (-1 == ret)
{
printf("read error:%s\\n", strerror(errno));
pthread_mutex_unlock(&mutex);
sem_post(&show_sem);
break;
}
pthread_mutex_unlock(&mutex);
//將信號量的值加一
sem_post(&show_sem);
}
}
close(fd);
return NULL;
}
void *print_thread(void *arg)
{
Student *pStu = (Student *)arg;
int i = 0;
while (1)
{
{
//如果show_sem大于0,接著往下執行,并且將該變量減一
//如果show_sem等于0,則阻塞,直到該值大于0
sem_wait(&show_sem);
pthread_mutex_lock(&mutex);
if (0 == pStu->iId)
{
pthread_mutex_unlock(&mutex);
sem_post(&read_sem);
break;
}
printf("id:%d, name:%s, sex:%c, score:%.1f\\n"
, pStu->iId, pStu->caName
, pStu->cSex, pStu->fScore);
pthread_mutex_unlock(&mutex);
//將信號量的值加一
sem_post(&read_sem);
}
}
return NULL;
}
int main(void)
{
pthread_mutex_init(&mutex, NULL);
//初始化信號量
sem_init(&read_sem, 0, 1); //將read_sem值置為1
sem_init(&show_sem, 0, 0); //將show_sem值置為0
Student stu;
pthread_t pthr_read;
pthread_t pthr_show;
pthread_create(&pthr_read, NULL, read_thread, &stu);
pthread_create(&pthr_show, NULL, print_thread, &stu);
pthread_join(pthr_read, NULL);
pthread_join(pthr_show, NULL);
return 0;
}
運算結果:
1.PNG
write_stu.c
#include <stdio.h>
#include <unistd.h> //write()
#include <errno.h> //errno
#include <string.h> //strerror()
/*open()*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define NAME_LEN 32
typedef struct Student
{
int iId;
char caName[NAME_LEN];
char cSex;
float fScore;
}Student;
int myOpen(const char *pathname)
{
int fd = -1;
if (NULL != pathname)
{
fd = open(pathname, O_WRONLY | O_CREAT | O_TRUNC
, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (-1 == fd)
{
printf("open error: %s\\n", strerror(errno));
}
}
return fd;
}
int main(void)
{
int fd = -1;
fd = myOpen("stu.info");
if (-1 != fd)
{
Student stu[6] = {{1001, "zhangsan", 'f', 99}
, {1002, "lisi", 'm', 79}
, {1003, "wangwu", 'f', 89}
, {1004, "zhaoliu", 'm', 69}
, {1005, "xiaoqi", 'm', 79}
, {1006, "laoba", 'f', 89}};
int ret = -1;
int i = 0;
for (; i < 6; i++)
{
ret = write(fd, stu+i, sizeof(Student));
if (-1 == ret)
{
printf("write error: %s\\n", strerror(errno));
}
else
{
printf("write %d bytes to file\\n", ret);
}
}
}
return 0;
}
運算結果:
1.PNG
think-eat.c
/*semget()*/
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h> //perror()
#include <unistd.h> //fork()
#include <stdio.h> //printf()
union semun
{
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT,IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
};
#if 0
int semop(int semid, struct sembuf *sops, unsigned nsops);
參數
semid:信號集的識別碼,可通過semget獲取。
sops:指向存儲信號操作結構的數組指針,信號操作結構的原型如下
struct sembuf
{
unsigned short sem_num; /* semaphore number */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
};
這三個字段的意義分別為:
sem_num:操作信號在信號集中的編號,第一個信號的編號是0。
sem_op:
1, 如果其值為正數,該值會加到現有的信號內含值中。
通常用于釋放所控資源的使用權;
2, 如果sem_op的值為負數,而其絕對值又大于信號的現值,
操作將會阻塞,直到信號值大于或等于sem_op的絕對值。
通常用于獲取資源的使用權;
3, 如果sem_op的值為0,如果沒有設置IPC_NOWAIT,
則調用該操作的進程或者線程將暫時睡眠,直到信號量的值為0; 否則,進程或者線程不會睡眠,函數返回錯誤EAGAIN。
sem_flg:信號操作標志,可能的選擇有兩種
1, IPC_NOWAIT //對信號的操作不能滿足時,semop()不會阻塞,
并立即返回,同時設定錯誤信息。
2, SEM_UNDO //程序結束時(不論正常或不正常),
保證信號值會被重設為semop()調用前的值。
這樣做的目的在于避免程序在異常情況下結束時
未將鎖定的資源解鎖,造成該資源永遠鎖定。
nsops:信號操作結構的數量,恒大于或等于1。
#endif
void getChopsticks(int iNum, int *semfd)
{
int iLeft = iNum;
int iRight = (iNum + 1)%5;
struct sembuf semope[2] = {{iLeft, -1, 0}
, {iRight, -1, 0}};
semop(*semfd, semope, 2);
}
void putChopsticks(int iNum, int *semfd)
{
int iLeft = iNum;
int iRight = (iNum + 1)%5;
struct sembuf semope[2] = {{iLeft, 1, 0}
, {iRight, 1, 0}};
semop(*semfd, semope, 2);
}
void thinkAndEat(int iNum, int *semfd)
{
while (1)
{
printf("%d say: I am thinking...\\n", iNum);
/*拿筷子吃飯*/
getChopsticks(iNum, semfd);
sleep(1);
printf("%d say: I am eatting...\\n", iNum);
/*放下筷子*/
putChopsticks(iNum, semfd);
printf("%d say: I am put chopsticks...\\n", iNum);
sleep(1);
}
}
int main(void)
{
int semfd = -1;
//獲得信號量集的標識,若信號量集不存在則創建
semfd = semget(0x1024, 5, IPC_CREAT | 0777);
if (-1 == semfd)
{
perror("semget");
return -1;
}
//對信號集中的信號量賦值
union semun sem;
sem.val = 1;
int i = 0;
for (; i < 5; i++)
{
if (-1 == semctl(semfd, i, SETVAL, sem))
{
perror("semctl");
return -1;
}
}
//創建五個哲學家進程
int num = 0; //表示第幾個哲學家
pid_t pid = -1;
for (i = 0; i < 4; i++)
{
pid = fork();
if (pid > 0) //parent
{
num = 4;
}
else if (0 == pid) //child
{
num = i;
break;
}
else if (-1 == pid) //error
{
return -1;
}
}
thinkAndEat(num, &semfd);
return 0;
}
運算結果:
2.PNG