No New New: Raw Pointers Removed from C++

Two weeks ago, the ISO C++ standard meeting took place in Jacksonville. Today I want to make a short detour and write about the revolutionary decision that was made in the Jacksonville meeting. Additionally, I refer to the Will no Longer Have Pointers by Fluent C++. The standard committee decided that pointers will be deprecated in C++20 and will with very high probability removed in C++23.

To be honest, what seems like a revolution is only the last step in a long evolution. First, let me explain the big picture.

 The evolution of pointers in C++

Pointers are part of C++ since the first beginning. We got them from C. From the first beginning there was always the tendency in C++ to make the handling with pointers more type-safe without paying the extra cost.

With C++98 we got std::auto_ptr to express exclusive ownership. But std::auto_ptr had a big issue. When you copy an std::auto_ptr the resource will be moved. What looks like a copy operation was actually a move operation. The graphic shows the surprising behaviour of an std::auto_ptr.

This was extremely bad and the reason for a lot of serious bugs; therefore, we got std::unique_ptr with C++11 and std::auto_ptr was deprecated in C++11 and finally removed in C++17. Additionally, we got std::shared_ptr and std::weak_ptr in C++11 for handling shared ownership. You can not copy but move an std::unique_ptr and if you copy or assign an std::shared_ptr, the internal reference counter will be increased. Have a look here:

Since C++11 C++ has a multithreading library. This makes the handling with std::shared_ptr quite challenging because an std::shared_ptr is per definition shared but not thread-safe. Only the control-block is thread-safe but not the access to its resource. That means, modifying the reference counter is an atomic operation and you have the guarantee that the resource will be deleted exactly once. This is the reason we will get with C++20 atomic smart pointers: std::atomic_shared_ptr and std::atmic_weak_ptr. Read the details in the proposal: Atomic Smart Pointers.

5 Best Eclipse Plugins: #1 (Eclox with Doxygen, Graphviz and Mscgen) | MCU on Eclipse

5 Best Eclipse Plugins: #1 (Eclox with Doxygen, Graphviz and Mscgen)Posted on June 25, 2012 by Erich Styger 24 VotesThe #1 award in my list goes to Eclox+Doxygen+Graphviz+Mscgen. Yes, it is a single Eclipse plugin (Eclox) for Doxygen, and with two other powerful tools. It solves a typical engineering problem: “How to document my project? And how to keep it up-to-date?”. Like many other engineers, I do not like to write documentation. Because it is painful. I want to write code and program. Writing documentation for it should be fun too. And it should solve the problem that the documentation does not match what has been implemented. I’m a big fan of the ‘single source’ concept: information has to be in a single place, and not copied and distributed among different places. And here my #1 helps me doing this.In a traditional way the following flow is used: Create a design, specify and document the API Implement the software Write the user documentation Ship it Maintain and ship and again, and again, and

Source: 5 Best Eclipse Plugins: #1 (Eclox with Doxygen, Graphviz and Mscgen) | MCU on Eclipse

Usefully for write and maintenance plugin for Eclipse…

  1. Doxygen: http://www.stack.nl/~dimitri/doxygen/ or www.doxygen.org
  2. Graphviz: http://www.graphviz.org
  3. Mscgen: http://www.mcternan.me.uk/mscgen/

after this article i use all of them.

Programowanie współbieżne C na Linux – przykłady

Przykładowe zadania z programowania współbieżnego na systemie Linux

  1. Napisz program, który pokazuje, które atrybuty procesu macierzystego są dziedziczone przez proces potomny uruchomiony za pomocą funkcji fork(), które zaś otrzymują nową wartość.
  2. Napisz program, który pokazuje, które atrybuty procesu są zachowane przez proces po wykonaniu funkcji exec().
  3. Napisz program, który wyświetla identyfikator procesu (PID) i nazwę związanego z nim polecenia dla wszystkich procesów uruchomionych przez użytkownika podanego w wierszu wywołania programu.
Wskazówka: informacje te można uzyskać przeglądając katalog /proc z plików (interesują nas katalogi, których właścicielem jest dany użytkownik) i pliki /proc/PID/status

Sources

C programing tutorial

 

Example solution 1 (draft)

# README #



## Uzupełnij program shell z o „ręczną” obsługę potoków.

Napisz program, który zbiera komunikaty od wielu programów i wyświetla je na ekranie. Do komunikacji użyj potoku nazwanego. Wskazówka: Utwórz program rdfifo, którego zadaniem jest utworzenie kolejki FIFO i czytanie z niej danych.

* Q: W jaki sposób przekażesz wspólną nazwę kolejki FIFO do tych programów?
* A: przez zmienną statyczą
* Q: W jaki sposób zapewnić działanie programu zbierającego komunikaty również wtedy, kiedy nie ma programu piszącego do łącza?
* A: przez proces pętli nieskończonej ze sleep
* Q: Jak zapewnić to, że komunikaty pochodzące od różnych programów wyświetlane są w całości, tzn. nie są rozdzielane  komunikatami od innych programów?
* A: flush? (do sprawdzenia).

### Zrzut z działania:

```
[23:30:20](pid 17400) DEBUG: Passed rdfifo 73 - while1

karol@carlo:~/eclipse-workspaces/unx_sys_programming/Debug$ ./unx_sys_programming -w

Input option value=(null) set program to write to FIFO

[23:30:20](pid 17411) DEBUG: Passed wrfifo 148 : mkfifo exist: 17
[23:30:20](pid 17411) DEBUG: Passed wrfifo 157 - pipe opened to read-write
[23:30:20](pid 17400) DEBUG: Passed rdfifo 104 - Remove FIFO
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #0 test PID: 17411: text -> Thu Jan 28 23:36:02 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #0 test PID: 17411: text -> Thu Jan 28 23:36:02 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #1 test PID: 17411: text -> Thu Jan 28 23:36:03 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #1 test PID: 17411: text -> Thu Jan 28 23:36:03 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #2 test PID: 17411: text -> Thu Jan 28 23:36:04 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #2 test PID: 17411: text -> Thu Jan 28 23:36:04 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #3 test PID: 17411: text -> Thu Jan 28 23:36:05 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #3 test PID: 17411: text -> Thu Jan 28 23:36:05 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #4 test PID: 17411: text -> Thu Jan 28 23:36:06 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #4 test PID: 17411: text -> Thu Jan 28 23:36:06 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #5 test PID: 17411: text -> Thu Jan 28 23:36:07 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #5 test PID: 17411: text -> Thu Jan 28 23:36:07 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #6 test PID: 17411: text -> Thu Jan 28 23:36:08 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #6 test PID: 17411: text -> Thu Jan 28 23:36:08 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #7 test PID: 17411: text -> Thu Jan 28 23:36:09 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #7 test PID: 17411: text -> Thu Jan 28 23:36:09 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #8 test PID: 17411: text -> Thu Jan 28 23:36:10 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #8 test PID: 17411: text -> Thu Jan 28 23:36:10 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #9 test PID: 17411: text -> Thu Jan 28 23:36:11 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #9 test PID: 17411: text -> Thu Jan 28 23:36:11 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 180 - close fd
[23:30:20](pid 17400) DEBUG: Passed rdfifo 112 - EOF reader

[10]   Done                    ./unx_sys_programming -r

bash:~/eclipse-workspaces/unx_sys_programming/Debug$ ./unx_sys_programming -h

Program FIFO
Program bez argumentów tworzy named pipe a w procesie potomnym zapisuje do niego dane.
Program mozna wywołać z argumentami tak aby działał jako odczyt (r) z pipe lub zapis do pipe (w).
Zapisywane są do pipe couner, PID i curenttime.

Usage: ./unx_sys_programming [-r] [-w]
```

## Przykład użycia


```
./unx_sys_programming

```

lub


```
./unx_sys_programming -r
./unx_sys_programming -w
./unx_sys_programming -w
./unx_sys_programming -w
```

# Fork read environ - zadania

* z1: Napisz program, który pokazuje, które atrybuty procesu macierzystego są dziedziczone przez proces potomny  uruchomiony za pomocą funkcji fork(), które zaś otrzymują nową wartość.
* z2: Napisz program, który pokazuje, które atrybuty procesu są zachowane przez proces po wykonaniu funkcji exec().
* z3: Napisz program, który wyświetla identyfikator procesu (PID) i nazwę związanego z nim polecenia dla wszystkich procesów uruchomionych przez użytkownika podanego w wierszu wywołania programu. Wskazówka: informacje te można uzyskać przeglądając katalog /proc z plików (interesują nas katalogi, których właścicielem jest dany  użytkownik) i pliki /proc/PID/status
 
Każdy proces charakteryzuje się pewnymi atrybutami. Należą do nich

 * Identyfikator procesu PID
 * Identyfikator procesu macierzystego PPID
 * Rzeczywisty identyfikator właściciela procesu
 * Rzeczywisty identyfikator grupy procesu
 * Efektywny identyfikator właściciela procesu
 * Efektywny identyfikator grupy procesu
 * Katalog bieżący i katalog główny
 * Maska tworzenia pliku
 * Identyfikator sesji
 * Terminal sterujący
 * Deskryptory otwartych plików
 * Ustalenia dotyczące obsługi sygnałów
 * Ustawienia zmiennych środowiskowych
 * Ograniczenia zasobów
 
Potomek dziedziczy z procesu potomnego wiele własności: rzeczywisty identyfikator użytkownika, rzeczywisty identyfikator grupy, obowiązujący identyfikator użytkownika, obowiązujący identyfikator grupy, identyfikatory dodatkowych grup, identyfikator sesji, terminal sterujący, sygnalizator ustanowienia identyfikatora użytkownika oraz sygnalizator ustanowienia identyfikatora grupy, deskryptory otwartych plików (są kopiowane) bieżący katalog roboczy, katalog główny,
 maskę tworzenia plików, maskę sygnałów oraz dyspozycje obsługi sygnałów, sygnalizator zamykania przy wywołaniu funkcji exec (close-on-exec) dla wszystkich otwartych deskryptorów plików, środowisko, przyłączone segmenty pamięci wspólnej,
 ograniczenia zasobów systemowych. Są jednak pewne różnice między procesem macierzystym a potomnym:
 wartość powrotu z funkcji fork, różne identyfikatory procesów, inne identyfikatory procesów macierzystych - w procesie potomnym jest to identyfikator procesu macierzystego; w procesie macierzystym identyfikator procesu macierzystego nie zmienia się, w procesie potomnym wartości tms_utime, tms_cutime i tms_ustime są równe 0,
 potomek nie dziedziczy rygli plików, ustalonych w procesie macierzystym, w procesie potomnym są zerowane wszystkie zaległe alarmy, w procesie potomnym jest zerowany zbiór zaległych sygnałów.
#include <asm-generic/errno-base.h>

/**
 * Uzupełnij program shell z o „ręczną” obsługę potoków.
 * ----------------------------------------------------
 * Napisz program, który zbiera komunikaty od wielu programów i wyświetla je na ekranie. Do komunikacji użyj potoku nazwanego.
 *
 * Wskazówka: Utwórz program rdfifo, którego zadaniem jest utworzenie kolejki FIFO i czytanie z niej danych.
 * Utwórz program wrfifo, który otwiera kolejkę FIFO tylko do zapisu i wpisuje do niej dane (np. swoj pid i czas).
 *
 * Q: W jaki sposób przekażesz wspólną nazwę kolejki FIFO do tych programów?
 * A: przez zmienną statyczą
 *
 * Q: W jaki sposób zapewnić działanie programu zbierającego komunikaty również wtedy, kiedy nie ma programu piszącego do łącza?
 * A: przez proces pętli nieskończonej ze sleep
 *
 * Q: Jak zapewnić to, że komunikaty pochodzące od różnych programów wyświetlane są w całości, tzn. nie są rozdzielane  komunikatami od innych programów?
 * A: flush? (do sprawdzenia).
 *
 */
#define DEBUG_MODE

#ifdef DEBUG_MODE
#define logs(...) printf("[%s](pid %d) DEBUG: Passed %s %d - %s\n", __TIME__, (int) getpid(), __FUNCTION__, __LINE__, ##__VA_ARGS__);
#define logs_d(...) printf("[%s](pid %d) DEBUG: Passed %s %d - %s : %d\n", __TIME__, (int) getpid(), __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define logs(...)
#endif

#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>

#define FIFOARG 1
#define PIPE_BUF 100
#define FIFO_PERMS (S_IRWXU | S_IWGRP| S_IWOTH)
#define FIFO "temp.fifo"

#define BUFFERSIZE 500000
char buf[BUFFERSIZE]; // read buf

char* mygettime() {
	time_t mytime;
	mytime = time(NULL);
	return (ctime(&mytime));
}

/**
 * Serwer read from named pipe
 * -----------------
 * @param argc
 * @param argv
 * @return
 */
int rdfifo() {

	int fifo, var;

	/* There are *two* ways the open can fail: the pipe doesn't exist
	 * yet, *or* it succeeded, but a different writer already opened
	 * it but didn't yet remove it.
	 */
	logs("reader start");
	while (1) {
		logs("while1");
		while ((fifo = open(FIFO, O_RDONLY)) == -1) {
			/* Since you didn't specify O_CREAT in the call to open, there
			 * is no way that FIFO would have been created by the
			 * reader.  If there *is* now a FIFO, a remove here
			 * would delete the one the writer created!
			 */
			sleep(1);
		}

		/* Get an exclusive lock on the file, failing if we can't get
		 * it immediately.  Only one reader will succeed.
		 */
		if (flock(fifo, LOCK_EX | LOCK_NB) == 0)
			break;

		/* We lost the race to another reader.  Give up and wait for
		 * the next writer.
		 */
		close(fifo);
	}
	/* We are definitely the only reader.
	 */

	/* *Here* we delete the pipe, now that we've locked it and thus
	 * know that we "own" the pipe.  If we delete before locking,
	 * there's a race where after we opened the pipe, a different
	 * reader also opened, deleted, and locked the file, and a new
	 * writer created a new pipe; in that case, we'd be deleting the
	 * wrong pipe.
	 */
	logs("Remove FIFO");
	remove(FIFO);
	while ((var = read(fifo, buf, BUFFERSIZE)) > 0) {
		printf("[%s](pid %d) DEBUG: Passed %s %d : reader reads record: %s", __TIME__, (int) getpid(), __FUNCTION__, __LINE__, buf);
		/* No need to sleep; we'll consume input as it becomes available. */
	}

	close(fifo);
	logs("EOF reader");
	exit(0);

}

/**
 * Klient named pipe
 *
 * write to pipe
 *
 * @param argc
 * @param argv
 * @return
 */
int wrfifo(pid_t pid) {
	// time structs
	time_t rawtime;
	struct tm * timeinfo;

	int len, i;
	char buf[PIPE_BUF];
	int fd;
	int communicates = 0;

//	if ((unlink(FIFO)) == -1) {
//		logs("Error unlink FIFO")
//	} else {
//		logs("unlink fifo");
//	}

	if ((mkfifo(FIFO, FIFO_PERMS) == -1) && (errno != EEXIST)) {
		logs("Server failed to create a FIFO");
		return (1);
	} else if (errno == ENOENT) {
		printf("[%s](pid %d) DEBUG: Passed %s %d : No such file or directory - mkfifo errno: %d\n", __TIME__, (int) getpid(), __FUNCTION__, __LINE__, errno);
	} else if (errno == EEXIST) {
		printf("[%s](pid %d) DEBUG: Passed %s %d : mkfifo exist: %d\n", __TIME__, (int) getpid(), __FUNCTION__, __LINE__, errno);
	} else {
		printf("[%s](pid %d) DEBUG: Passed %s %d : No such file or directory - mkfifo errno: %d\n", __TIME__, (int) getpid(), __FUNCTION__, __LINE__, errno);
	}

	if ((fd = open(FIFO, O_WRONLY)) == -1) {
		logs("Client failed to open log fifo for writing");
		return (1);
	} else {
		logs("pipe opened to read-write");
	}

	/**
	 * write some text to pipe
	 */
	for (i = 0; i < 10; i++) {
		sleep(1);
		//logs("time")
		time(&rawtime);
		timeinfo = localtime(&rawtime);
		sprintf(buf, "#%d test PID: %d: text -> %s", communicates++, (int) getpid(), asctime(timeinfo));
		len = strlen(buf);
		if (write(fd, buf, len) != len) {
			logs("Client failed to write");
			return (1);
		} else {
			printf("[%s](pid %d) DEBUG: Passed %s %d : client succesed write to pipe: %s", __TIME__, (int) getpid(), __FUNCTION__, __LINE__, buf);
		}
	}
	/* Wait for the child process to finish. */
	waitpid(pid, NULL, 0);
	sleep(1);
	logs("close fd");
	close(fd);
	return (0);
}

/**
 * main
 *
 * @return
 */
int main(int argc, char *argv[]) {
	pid_t pid;
	int i;

	/**
	 * analiza lini komend
	 *
	 */
	int opt = 0;
	char *in_fname = NULL;
	char *out_fname = NULL;

	/**
	 * funkcje programu
	 */
	while ((opt = getopt(argc, argv, "rwh")) != -1) {
		switch (opt) {
		case 'r':
			in_fname = optarg;
			printf("\nInput option value=%s set program read from FIFO", in_fname);
			rdfifo();
			exit(0);
			break;
		case 'w':
			out_fname = optarg;
			printf("\nInput option value=%s set program to write to FIFO", out_fname);
			wrfifo(pid);
			exit(0);
			break;
		case '?':
		case 'help':
		case 'h':
		default:
			printf("\nProgram FIFO\n");
			printf("------------\n");
			printf("Program bez argumentów tworzy named pipe a w procesie potomnym zapisuje do niego dane.\n");
			printf("Program mozna wywołać z argumentami tak aby działał jako odczyt (r) z pipe lub zapis do pipe (w).\n");
			printf("Zapisywane są do pipe couner, PID i curenttime.\n\n");
			printf("Usage: %s [-r] [-w]\n\n", argv[0]);

			exit(0);
			break;
		}
	}

	logs("start program");

	pid = fork();

	/* proces potomny */
	if (pid == (pid_t) 0) { /* brak obsługi błędów */
		/**
		 * Odczytywanie
		 */
		for (i = 0; i < 3; i++) {
			rdfifo();
			sleep(1);
		}
	}
	/* proces macierzysty */
	else {
		for (i = 0; i < 5; i++) {
			wrfifo(pid);

		}
	}
	logs("end main");
	return (0);
}

Zrzut z działania

[23:30:20](pid 17400) DEBUG: Passed rdfifo 73 - while1

karol@carlo:~/eclipse-workspaces/unx_sys_programming/Debug$ ./unx_sys_programming -w

Input option value=(null) set program to write to FIFO

[23:30:20](pid 17411) DEBUG: Passed wrfifo 148 : mkfifo exist: 17
[23:30:20](pid 17411) DEBUG: Passed wrfifo 157 - pipe opened to read-write
[23:30:20](pid 17400) DEBUG: Passed rdfifo 104 - Remove FIFO
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #0 test PID: 17411: text -> Thu Jan 28 23:36:02 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #0 test PID: 17411: text -> Thu Jan 28 23:36:02 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #1 test PID: 17411: text -> Thu Jan 28 23:36:03 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #1 test PID: 17411: text -> Thu Jan 28 23:36:03 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #2 test PID: 17411: text -> Thu Jan 28 23:36:04 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #2 test PID: 17411: text -> Thu Jan 28 23:36:04 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #3 test PID: 17411: text -> Thu Jan 28 23:36:05 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #3 test PID: 17411: text -> Thu Jan 28 23:36:05 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #4 test PID: 17411: text -> Thu Jan 28 23:36:06 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #4 test PID: 17411: text -> Thu Jan 28 23:36:06 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #5 test PID: 17411: text -> Thu Jan 28 23:36:07 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #5 test PID: 17411: text -> Thu Jan 28 23:36:07 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #6 test PID: 17411: text -> Thu Jan 28 23:36:08 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #6 test PID: 17411: text -> Thu Jan 28 23:36:08 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #7 test PID: 17411: text -> Thu Jan 28 23:36:09 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #7 test PID: 17411: text -> Thu Jan 28 23:36:09 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #8 test PID: 17411: text -> Thu Jan 28 23:36:10 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #8 test PID: 17411: text -> Thu Jan 28 23:36:10 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 174 : client succesed write to pipe: #9 test PID: 17411: text -> Thu Jan 28 23:36:11 2016
[23:30:20](pid 17400) DEBUG: Passed rdfifo 107 : reader reads record: #9 test PID: 17411: text -> Thu Jan 28 23:36:11 2016
[23:30:20](pid 17411) DEBUG: Passed wrfifo 180 - close fd
[23:30:20](pid 17400) DEBUG: Passed rdfifo 112 - EOF reader

[10]   Done                    ./unx_sys_programming -r

bash:~/eclipse-workspaces/unx_sys_programming/Debug$ ./unx_sys_programming -h

Program FIFO
Program bez argumentów tworzy named pipe a w procesie potomnym zapisuje do niego dane.
Program mozna wywołać z argumentami tak aby działał jako odczyt (r) z pipe lub zapis do pipe (w).
Zapisywane są do pipe couner, PID i curenttime.

Usage: ./unx_sys_programming [-r] [-w]

Example solution 2 (draft)

/**
 * Zadania
 * -------
 * z1: Napisz program, który pokazuje, które atrybuty procesu macierzystego są dziedziczone przez proces potomny  uruchomiony za pomocą funkcji fork(), które zaś otrzymują nową wartość.
 * z2: Napisz program, który pokazuje, które atrybuty procesu są zachowane przez proces po wykonaniu funkcji exec().
 * z3: Napisz program, który wyświetla identyfikator procesu (PID) i nazwę związanego z nim polecenia dla wszystkich procesów uruchomionych przez użytkownika podanego w wierszu wywołania programu. Wskazówka: informacje te można uzyskać przeglądając katalog /proc z plików (interesują nas katalogi, których właścicielem jest dany  użytkownik) i pliki /proc/PID/status
 *
 * Każdy proces charakteryzuje się pewnymi atrybutami. Należą do nich:
 * Identyfikator procesu PID
 * Identyfikator procesu macierzystego PPID
 * Rzeczywisty identyfikator właściciela procesu
 * Rzeczywisty identyfikator grupy procesu
 * Efektywny identyfikator właściciela procesu
 * Efektywny identyfikator grupy procesu
 * Katalog bieżący i katalog główny
 * Maska tworzenia pliku
 * Identyfikator sesji
 * Terminal sterujący
 * Deskryptory otwartych plików
 * Ustalenia dotyczące obsługi sygnałów
 * Ustawienia zmiennych środowiskowych
 * Ograniczenia zasobów
 *
 *
 * Potomek dziedziczy z procesu potomnego wiele własności:
 rzeczywisty identyfikator użytkownika, rzeczywisty identyfikator grupy, obowiązujący identyfikator użytkownika, obowiązujący identyfikator grupy,
 identyfikatory dodatkowych grup,
 identyfikator sesji,
 terminal sterujący,
 sygnalizator ustanowienia identyfikatora użytkownika oraz sygnalizator ustanowienia identyfikatora grupy,
 deskryptory otwartych plików (są kopiowane)
 bieżący katalog roboczy,
 katalog główny,
 maskę tworzenia plików,
 maskę sygnałów oraz dyspozycje obsługi sygnałów,
 sygnalizator zamykania przy wywołaniu funkcji exec (close-on-exec) dla wszystkich otwartych deskryptorów plików,
 środowisko,
 przyłączone segmenty pamięci wspólnej,
 ograniczenia zasobów systemowych.
 Są jednak pewne różnice między procesem macierzystym a potomnym:
 wartość powrotu z funkcji fork,
 różne identyfikatory procesów,
 inne identyfikatory procesów macierzystych - w procesie potomnym jest to identyfikator procesu macierzystego; w procesie macierzystym identyfikator procesu macierzystego nie zmienia się,
 w procesie potomnym wartości tms_utime, tms_cutime i tms_ustime są równe 0,
 potomek nie dziedziczy rygli plików, ustalonych w procesie macierzystym,
 w procesie potomnym są zerowane wszystkie zaległe alarmy,
 w procesie potomnym jest zerowany zbiór zaległych sygnałów.
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

extern char** environ;
char *prt_parent;

int glob = 1; 			// zewnętrzna zmienna

/* Prints the environment, one environment variable to a line, of the
 process given by PID. */
char *print_process_environment(pid_t pid) {
	int fd;
	char filename[24];
	char environment[8192];
	size_t length;
	char* next_var;
	/* Generate the name of the environ file for the process. */
	snprintf(filename, sizeof(filename), "/proc/%d/environ", (int) pid);
	/* Read the contents of the file. */
	fd = open(filename, O_RDONLY);
	length = sizeof(environ);
	printf("Size of environ: %d\n", length);
	close(fd);
	/* read does not NUL-terminate the buffer, so do it here. */
	environment[length] = '\0';
	/* Loop over variables. Variables are separated by NULs. */
	next_var = environment;
	while (next_var < environment + length) {
		/* Print the variable. Each is NUL-terminated, so just treat it
		 like an ordinary string. */
		printf(">> %s\n", next_var);
		/* Advance to the next variable. Since each variable is
		 NUL-terminated, strlen counts the length of the next variable,
		 not the entire variable list. */
		next_var += strlen(next_var) + 1;
	}
	return (environment);
}

//int main(int argc, char* argv[]) {
//pid_t pid = (pid_t) atoi (argv[1]);
//print_process_environment (pid);
///return 0;
//}

int main1(int argc, char **argv) {
	int var = 100; 		        // zmienna automatyczna na stows
	char **env = environ;		// środowisko parent
	// zapamiętanie environ w tablicy

	printf("PROGRAM Z1\n\n");
	printf("Zmienne srodowiskowe parent: ----------------------------\n");
	while (*env) {
		printf("%s\n", *env++);
	}

	printf("---------------------------------------------------------\n");

	//for (int i = 0; *env != NULL && gets(env[i]); i++)
	//	prt_parent[i] = env[i];

	pid_t pid = fork();

	if (pid == 0) {
		// child process
		glob++;
		var++;
		printf("child process: pid %d, ppid %d, getuid %d, geteuid %d, getgid %d, glob = %d, var = %d\n", getpid(), getppid(), getuid(), geteuid(), getgid(),
				glob, var);

		/**
		 * wy swietlenie zmiennych środowiskowych różnych od parent
		 */
		printf("Zmienne srodowiskowe child różne od parent:\n");
		char environment_1[8192];
		char * prt_env = &environment_1;
		prt_env = print_process_environment(pid);
		char **env_child = environ;
		printf("Size of *char: %d\n", sizeof(environ));

		while (*env_child) {
			printf("compare - %s %d\n", *env_child, strcmp(*env_child++, *env++));
			//printf("%s -----\n", *env2++);
			//if (strcmp(*env2, ++*env) == 0) {
			//
			//} else {
			//printf("%s jest takie samo\n", *env2);
			//}
			//*env_child++;
			//*env++;
		}
		printf("-------------------- x --------------------\n");

	} else if (pid > 0) {
		// parent process
		printf("parent process: pid %d, ppid %d, getuid %d, geteuid %d, getgid %d, glob = %d, var = %d\n", getpid(), getppid(), getuid(), geteuid(), getgid(),
				glob, var);
	} else {
		// fork failed
		printf("fork() failed!\n");
		return (1);
	}

	printf("-- end of program pid %d\n", getpid());

	return (0);
}

Using fork() in C/C++ – a minimum working example

In a C or C++ program, fork() can be used to create a new process, known as a child process. This child is initially a copy of the the parent, but can be used to run a different branch of the program or even execute a completely different program. After forking, child and parent processes run in parallel. Any variables local to the parent process will have been copied for the child process, so updating a variable in one process will not affect the other.

Consider the following example program:

#include <stdio .h>
#include <unistd .h>
#include <stdlib .h>
#include <string .h>
#include <sys /types.h>
#include </sys><sys /resource.h>
#include <fcntl .h>
#include <sys /stat.h>
#include </sys><sys /types.h>
#include <unistd .h>
int main(int argc, char **argv)
{
printf("--beginning of program\n");
 
int counter = 0;
pid_t pid = fork();
 
if (pid == 0)
{
// child process
int i = 0;
for (; i < 5; ++i) { printf("child process: counter=%d\n", ++counter); } } else if (pid > 0)
{
// parent process
int j = 0;
for (; j < 5; ++j)
{
printf("parent process: counter=%d\n", ++counter);
}
}
else
{
// fork failed
printf("fork() failed!\n");
return 1;
}
 
printf("--end of program--\n");
 
return 0;
}

This program declares a counter variable, set to zero, before fork()ing. After the fork call, we have two processes running in parallel, both incrementing their own version of counter. Each process will run to completion and exit. Because the processes run in parallel, we have no way of knowing which will finish first. Running this program will print something similar to what is shown below, though results may vary from one run to the next.

Automat komórkowy w C | Cellular automaton (CA) in C

Cellular automata and Moore neighborhood

Cellular automaton (CA) is by definition a periodic grid of cells, where in each cell sits a finite automaton, and a set of (identical) rules for every such automaton describing to which state it switches on a next moment of discrete time ti+1, depending of its own state and states of all its neighbors on a current moment of time ti. For now, we will be interested in 2d, rectangular CA, and a neighborhood which includes 8 neighbors of the cell. This is what is called the Moore neighborhood, because it was invented by Edward Moore.

Rules Brain

http://zvold.blogspot.com/2010/01/conways-life-and-brians-brain-cellular.html

  • Each cell has three possible states: passive, active, and semi-active.
  • If a cell is active, it goes to semi-active state on the next step
  • If a cell is semi-active, it becomes passive on the next step
  • If a cell is passive, it becomes active if and only if it has exactly 2 active neighbors

Materials

Source

 

Proudly powered by WordPress | Theme: Baskerville 2 by Anders Noren.

Up ↑