v rámci přípravy jsem si vypracoval pár příkladů podobných minulým zkouškám. Upozorňuji, že jsem UNIXové API nikdy moc nepoužíval, takže tam budou různé věci blbě.
Budete potřebovat nsautil.h a jcc z blobutils
Zdroje: http://mff.devnull.cz/pvu/common/zkousk ... ousek.html a toto fórum.
Příklad: Nasimulujte shellovou kolonu cat /proc/cpuinfo | grep model | tr a-z A-Z | sed -r "s/(A|E|I|O|U)/_/g"
Kód: Vybrat vše
#include <nsautil.h>
int main(int argc, char **argv) {
pid_t child;
int filedes[2];
int pipeprev = -1;
pipe(filedes);
child = fork();
if(child == 0) {
dup2(filedes[1], STDOUT_FILENO);
close(filedes[1]);
execlp("cat", "cat", "/proc/cpuinfo", NULL);
}
close(filedes[1]);
close(STDIN_FILENO);
pipeprev = filedes[0];
pipe(filedes);
child = fork();
if(child == 0) {
dup2(pipeprev, STDIN_FILENO);
dup2(filedes[1], STDOUT_FILENO);
close(filedes[1]);
execlp("grep", "grep", "model", NULL);
}
close(filedes[1]);
close(pipeprev);
pipeprev = filedes[0];
pipe(filedes);
child = fork();
if(child == 0) {
dup2(pipeprev, STDIN_FILENO);
dup2(filedes[1], STDOUT_FILENO);
close(filedes[1]);
execlp("tr", "tr", "a-z", "A-Z", NULL);
}
close(filedes[1]);
close(pipeprev);
child = fork();
if(child == 0) {
dup2(filedes[0], STDIN_FILENO);
//close(filedes[0]);
execlp("sed", "sed", "-r", "s/(A|E|I|O|U)/_/g", NULL);
}
close(filedes[0]);
return 0;
}
Příklad: Hlavní vlákno vytvoří počet vláken zadaný jako parametr příkazové řádky. Každé vlákno simuluje činnost pomocí sleep() na náhodnou dobu, 1 až 10 sekund. Po vykonání činnosti, tj. po ukočení funkce sleep(), vlákno zahlásí hlavnímu vláknu, že skončilo. Hlavní vlákno okamžitě vytvoří další vlákno.
Cílem je tedy udržovat stále stejný počet vláken v běhu. Každé vlákno má navíc svoje pořadové číslo, při vytvoření a zániku vlákna se vypíše na termínál hlášení o této skutečnosti, s použitím pořadového čísla.
Pro synchronizaci použijte mutexy a podmínkové proměnné. Aktivní čekání je nepřípustné. Velký důraz je kladen na korektnost použití synchronizačních primitiv.
Usage: ./pthreads 10
Kód: Vybrat vše
#include <nsautil.h>
#include <pthread.h>
#include <poll.h>
pthread_mutex_t mujmutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t mojecond = PTHREAD_COND_INITIALIZER;
int numt;
int * r;
typedef struct tr {
int tid;
int toffs;
char * message;
pthread_t thr;
} tr;
tr * t;
void * mujthread(void *ptr) {
tr * ctx = (tr*)ptr;
printf("Thread %i(%i) is running
", ctx->toffs, ctx->tid);
poll(NULL, 0, random() % 10000);
// for(volatile int i = 0; i<100*1000*1000; i++) {}
printf("Thread %i(%i) says: %s
", ctx->toffs, ctx->tid, ctx->message);
poll(NULL, 0, random() % 10000);
printf("Thread %i(%i) is finishing
", ctx->toffs, ctx->tid);
r[ctx->tid] = 0;
pthread_cond_signal(&mojecond);
return(NULL);
}
int main(int argc, char ** argv) {
numt = atoi(argv[1]);
r = malloc(sizeof(int) * numt);
t = malloc(sizeof(tr) * numt);
int iter = 0;
int toffs = 0;
while (1) {
pthread_mutex_lock(&mujmutex);
iter++;
for (int i = 0; i<numt; i++) {
if (r[i] == 0) {
pthread_join(t[i].thr, NULL);
pthread_t thr;
t[i].message = (char*)malloc(100);
sprintf(t[i].message, "This is iter %i", iter);
t[i].tid = i;
t[i].toffs = toffs;
int ret = pthread_create(&thr, NULL, &mujthread, (void*) (t + i));
t[i].thr = thr;
toffs++;
if(ret == 0) {
r[i] = 1;
} else {
printf("Cannot create thread!
");
}
}
}
pthread_cond_wait(&mojecond, &mujmutex);
pthread_mutex_unlock(&mujmutex);
}
exit(EXIT_SUCCESS);
}
Usage: $ ./server 6666
$ date | nc -u :: 6666
Vrátí datum s čísly přepsanými křížky.
Kód: Vybrat vše
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#define BUF_SIZE 500
/* Zkopírováno z manpage getaddrinfo z glibc a z https://stackoverflow.com/questions/5956516/getaddrinfo-and-ipv6 */
int main(int argc, char *argv[]) {
struct addrinfo hints;
struct addrinfo *result, *rp;
int sfd, s;
struct sockaddr_storage peer_addr;
socklen_t peer_addr_len;
ssize_t nread;
char buf[BUF_SIZE];
if (argc != 2) {
fprintf(stderr, "Usage: %s port
", argv[0]);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
hints.ai_protocol = 0; /* Any protocol */
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
s = getaddrinfo(NULL, argv[1], &hints, &result);
//s = getaddrinfo("localhost", argv[1], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s
", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully bind(2).
If socket(2) (or bind(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
if(rp->ai_family == AF_INET6) {
char * buf = malloc(INET6_ADDRSTRLEN);
struct sockaddr_in* saddr = (struct sockaddr_in*)rp->ai_addr;
if(inet_ntop(AF_INET6, &(saddr->sin_addr), buf, INET6_ADDRSTRLEN)) {
printf("Trying (v6) %s
", buf);
} else {
printf("ntop err
");
}
} else if (rp->ai_family == AF_INET) {
char * buf = malloc(INET_ADDRSTRLEN);
struct sockaddr_in* saddr = (struct sockaddr_in*)rp->ai_addr;
if(inet_ntop(AF_INET, &(saddr->sin_addr), buf, INET_ADDRSTRLEN)) {
printf("Trying (v4) %s
", buf);
} else {
printf("ntop err
");
}
}
if(rp->ai_family == AF_INET) {
continue;
}
sfd = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sfd == -1) {
continue;
}
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0) {
printf(" ...bound OK
");
break;
}
close(sfd);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not bind
");
exit(EXIT_FAILURE);
}
freeaddrinfo(result); /* No longer needed */
/* Read datagrams and echo them back to sender */
for (;;) {
peer_addr_len = sizeof(struct sockaddr_storage);
nread = recvfrom(sfd, buf, BUF_SIZE, 0,
(struct sockaddr *) &peer_addr, &peer_addr_len);
if (nread == -1)
continue; /* Ignore failed request */
char host[NI_MAXHOST], service[NI_MAXSERV];
s = getnameinfo((struct sockaddr *) &peer_addr,
peer_addr_len, host, NI_MAXHOST,
service, NI_MAXSERV, NI_NUMERICSERV);
if (s == 0)
printf("Received %ld bytes from %s:%s
",
(long) nread, host, service);
else
fprintf(stderr, "getnameinfo: %s
", gai_strerror(s));
for(int i = 0; i<nread; i++) {
if(buf[i] >= '0' &&buf[i] <= '9') {
buf[i] = '#';
}
}
if (sendto(sfd, buf, nread, 0,
(struct sockaddr *) &peer_addr,
peer_addr_len) != nread)
fprintf(stderr, "Error sending response
");
}
}